2011-02-07 4 views
2

Я написал следующий код, чтобы установить курсор Gtk::Window с Cairo::Context. Когда я запускаю программу и перемещаю курсор в окно, курсор меняется на горизонтальную черную линию вверху, а затем внизу отображается неопределенная белая фигура. Я ожидал, что курсор превратится в черный квадрат 16 × 16. Почему курсор не принимает форму, которую я намеревался?Gtk +: Как установить курсор окна из контекста Каира?

#include <gtkmm.h> 

const int size = 16, hotspot = 0; 

class Window : public Gtk::Window 
{ 
    public: 
    void change_cursor() 
    { 
     Glib::RefPtr<Gdk::Drawable> pixmap = Gdk::Pixmap::create(
      Glib::RefPtr<Gdk::Drawable>(), size, size, get_window()->get_depth()); 
     pixmap->set_colormap(get_window()->get_colormap()); 
     Cairo::RefPtr<Cairo::Context> context = pixmap->create_cairo_context(); 
     context->set_source_rgba(0, 0, 0, 0); 
     context->rectangle(0, 0, size, size); 
     context->fill(); 
     Glib::RefPtr<Gdk::Pixbuf> pixbuf 
      = Gdk::Pixbuf::create(pixmap, 0, 0, size, size); 
     Gdk::Cursor cursor(get_window()->get_display(), pixbuf, hotspot, hotspot); 
     window->set_cursor(cursor); 
    } 
}; 

int main(int argc, char* argv[]) 
{ 
    Gtk::Main app(argc, argv); 
    Window window; 
    window.show_all(); 
    window.change_cursor(); 
    Gtk::Main::run(window); 
    return 0; 
} 

Когда я рисую Gdk::Pixmap на экран, он выглядит отлично. Когда я рисую Gdk::Pixbuf на экран, я получаю мусор.

ответ

2

я не выяснить причину проблемы, а способ его обойти:

  1. Создание пустой Gdk::Pixbuf.
  2. Создайте Cairo::ImageSurface используя пиксели Gdk::Pixbuf в качестве буфера данных.
  3. Создайте Cairo::Context с Cairo::ImageSurface.
  4. Очистите Cairo::Context (это важно, потому что данные пикселя Gdk::Pixbuf пока не инициализированы).

код выглядит следующим образом:

Glib::RefPtr<Gdk::Pixbuf> pixbuf 
    = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, size, size); 
Cairo::RefPtr<Cairo::ImageSurface> surface 
    = Cairo::ImageSurface::create(
      pixbuf->get_pixels(), Cairo::FORMAT_ARGB32, 
      size, size, pixbuf->get_rowstride()); 
Cairo::RefPtr<Cairo::Context> context = Cairo::Context::create(surface); 
context->save(); 
context->set_operator(Cairo::OPERATOR_CLEAR); 
context->paint(); 
context->restore(); 

Когда я теперь рисовать в этом контексте и установить курсор из Gdk::Pixbuf, я получаю почти что я хочу: форма отлично, но красный и Blue заменены. Это можно зафиксировать, как указано в Question 4291994 (How to write contents of a Cairo Image surface into a Gdk Pixbuf?):

void fix_buffer_after_cairo(Glib::RefPtr<Gdk::Pixbuf> pixbuf) 
    { 
    guint8* pixels = pixbuf->get_pixels(); 
    int height = pixbuf->get_height(); 
    int width = pixbuf->get_width(); 
    int rowstride = pixbuf->get_rowstride(); 

    guint8 tmp; 
    guint8* p; 
    guint8* end; 

    for (int j = height; j > 0; --j) 
    { 
     p = pixels; 
     end = p + 4 * width; 
     while (p < end) 
     { 
     tmp = p[0]; 
     if (G_BYTE_ORDER == G_LITTLE_ENDIAN) 
     { 
      p[0] = p[2]; p[2] = tmp; 
     } 
     else 
     { 
      p[0] = p[1]; p[1] = p[2]; p[2] = p[3]; p[3] = tmp; 
     } 
     p += 4; 
     } 
     pixels += rowstride; 
    } 
    } 
}