Gtk+:如何从 Cairo 上下文中设置窗口的光标?

Posted

技术标签:

【中文标题】Gtk+:如何从 Cairo 上下文中设置窗口的光标?【英文标题】:Gtk+: How to set the cursor of a window from a Cairo context? 【发布时间】:2011-02-07 08:29:49 【问题描述】:

我编写了以下代码来设置Gtk::Window 的光标从Cairo::Context。当我运行程序并将光标移动到窗口中时,光标在顶部变为水平黑线,然后在底部出现一些无法定义的白色形状。我期待光标变成一个黑色的 16×16 正方形。为什么光标没有呈现我想要的形状?

#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 绘制到屏幕上时,我得到了垃圾。

【问题讨论】:

【参考方案1】:

我没有弄清楚问题的原因,但有办法解决它:

    创建一个空的Gdk::Pixbuf。 使用Gdk::Pixbuf 的像素作为数据缓冲区创建Cairo::ImageSurface。 从Cairo::ImageSurface 创建一个Cairo::Context。 清除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;
    
  

【讨论】:

以上是关于Gtk+:如何从 Cairo 上下文中设置窗口的光标?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Gtk 下创建 cairo-gl 曲面

如何使用 Cairo 和 Gtk3 在 GtkDrawingArea 中绘制一条线

gjs cairo 上下文绘图未显示在杂乱的窗口中

cairo图形库

Gtk3 和 cairo g_timeout_add 不起作用

cairo / gdk / gtk 中是不是支持 HSV 颜色模型?