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

发布于 2024-10-16 07:47:20 字数 1235 浏览 8 评论 0原文

我编写了以下代码来从 Cairo::Context 设置 Gtk::Window 的光标。当我运行程序并将光标移动到窗口中时,光标变为顶部的水平黑线,然后是底部的一些无法定义的白色形状。我原以为光标会变成黑色的 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 绘制到屏幕上时,我得到了垃圾。

I have written the following code to set the cursor of a Gtk::Window from a Cairo::Context. When I run the program and move the cursor into the window, the cursor changes to a horizontal black line at the top, followed by some undefinable white shape at the bottom. I was expecting the cursor to change into a black 16×16 square. Why doesn't the cursor assume the shape I intended?

#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;
}

When I draw the Gdk::Pixmap to the screen, it looks fine. When I draw the Gdk::Pixbuf to the screen, I get garbage.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

只等公子 2024-10-23 07:47:20

我没有找出问题的原因,但有一种解决方法:

  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 设置光标时,我几乎得到了我想要的:形状很好,但红色和蓝色交换了。可以按照问题 4291994(如何将 Cairo 图像表面的内容写入 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;
    }
  }
}

I did not figure out the cause of the problem, but a way to work around it:

  1. Create an empty Gdk::Pixbuf.
  2. Create a Cairo::ImageSurface using the Gdk::Pixbuf's pixels as data buffer.
  3. Create a Cairo::Context from the Cairo::ImageSurface.
  4. Clear the Cairo::Context (this is important, because Gdk::Pixbuf's pixel data seem not to be initialized yet).

The code looks like this:

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();

When I now paint to that context and set the cursor from the Gdk::Pixbuf, I get almost what I want: the shape is fine, but Red and Blue are swapped. This can be fixed as outlined in 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;
    }
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文