2011-02-07 25 views
2

我寫了下面的代碼來設置Cairo::ContextGtk::Window的遊標。當我運行該程序並將光標移動到窗口中時,光標變爲頂部的水平黑線,然後是底部的一些不可定義的白色形狀。我期待光標變成黑色的16×16方塊。爲什麼光標不會呈現我想要的形狀?Gtk +:如何從Cairo上下文設置窗口的光標?

#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. 使用Gdk::Pixbuf的像素作爲數據緩衝區創建Cairo::ImageSurface
  3. Cairo::ImageSurface創建Cairo::Context
  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設置光標,我得到幾乎我想要的東西:形狀是好的,但紅和藍色交換。這可以如在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; 
    } 
    } 
}