开罗和Qt的集成

16

我想在Qt中使用Cairo图形库,但找不到任何文档。我只是想使用Qt制作GUI,并在Qt窗口中使用Cairo进行图形绘制。

谢谢。

5个回答

13

从cairo 1.17.8开始,Qt支持将被上游删除

旧答案

cairo的最新版本支持Qt,通过允许使用cairo_qt_surface_create(QPainter *painter)创建的表面进行绘制:您可以在此处检查相关的头文件。因为此功能仍处于实验性阶段且默认情况下已禁用,所以没有文档(您应该通过使用configure --enable-qt显式启用Qt支持来编译cairo)。


我一定会尝试这个,真的希望它能够成功,因为现在我正在尝试GTK,但它不如Qt好用。 - Andrei
1
如果您正在使用C ++,我认为使用C ++绑定会更加舒适,而不是使用纯GTK+。Qt和QPainter、GTK+和cairo、gtkmm和cairomm以及任何有效的混合...根据您想要的内容,它们都是有效的选项。 - ntd
Cairo Qt表面目前无法与Qt6一起使用,需要进行小修补才能与Qt5一起使用。 - user1095108

8

Qt的绘图系统是一个非常好的绘图库,是基于矢量的。而且它已经存在了。如果你选择Qt作为你的GUI工具包,那么就再也没有更简单的了。


@amc 这不正确。大多数绘图设备都是基于光栅的,但是也有矢量设备,例如 QPdfWriter。QPainter API 本身主要由基于矢量的操作组成,它不仅仅是一个位块传输器。 - andref
如果可以避免的话,在你的Qt应用程序中不要使用cairo,这个答案是100%正确的。 - user1095108

4
注意: 这不是你想要的答案。
你确定要这样做吗?为了什么目的?你是想基于Cairo编写一个QPaintDevice吗?Qt已经实现了自己的图形原语,同样的,Cairo也有。我唯一能看到的理由是你不想让Qt的重量级层干扰你的系统(嵌入式?)。这就好像你试图使用Cairo的DirectFB后端,但是还有像运行在DirectFB上的Qt等其他问题。然而,需要注意的是,这样的实现是昂贵的,并且不是免费的,其本身也存在一些缺陷,例如库交互性问题、从此基于Cairo的上下文打印等。我建议你在Google上进行正常搜索,查看是否正在进行或曾经进行过这样的努力,并在尝试之前非常认真地权衡利弊。


谢谢您的回答。我只需要一个简单的图形库和一个GUI库,它们可以非常容易地协同工作,并且我不想使用GUI库函数进行绘图,我喜欢Cairo因为它易于使用并且是基于矢量的。也许您可以向我推荐另一个GUI库。 - Andrei
这是我不理解的部分,为什么你不想使用Qt呢?也许我们可以提供一个替代方案。Qt不仅仅是GUI。图形库比GUI库更低级别的抽象。在我看来,你正在退步。GTK+是另一个带有Cairo后端的GUI库。 - dirkgently
我将尝试使用Qt图形函数。我尝试过GTK,但在项目中使用起来很麻烦。 - Andrei
有时我们编写的程序仅使用Qt的内部工具,其余部分都是基于cairo的。这就是为什么人们可能需要在由Qt制作的UI小部件中使用cairo进行绘画的原因。 - Петър Петров

1
这是一个可能的示例:

这是如何完成的:

class CairoWidget: public QWidget
{
public:
  using QWidget::QWidget;

private:
  void paintEvent(QPaintEvent*)
  {
    auto const w(width()), h(height());
    QImage image(w, h, QImage::Format_RGB32);

    auto const surf(cairo_image_surface_create_for_data(image.bits(),
      CAIRO_FORMAT_RGB24, w, h, image.bytesPerLine()));
    auto const cr(cairo_create(surf));
    cairo_surface_destroy(surf);

    //
    cairo_set_source_rgb(cr, 1, 1, 1);
    cairo_paint(cr);
    cairo_scale(cr, w, h);

    //
    cairo_set_source_rgb(cr, 0, 0, 0);
    cairo_move_to(cr, 0, 0);
    cairo_line_to(cr, 1, 1);
    cairo_move_to(cr, 1, 0);
    cairo_line_to(cr, 0, 1);
    cairo_set_line_width(cr, .2);
    cairo_stroke(cr);

    cairo_rectangle(cr, 0, 0, .5, .5);
    cairo_set_source_rgba(cr, 1, 0, 0, .80);
    cairo_fill(cr);

    cairo_rectangle(cr, 0, .5, .5, .5);
    cairo_set_source_rgba(cr, 0, 1, 0, .60);
    cairo_fill(cr);

    cairo_rectangle(cr, .5, 0, .5, .5);
    cairo_set_source_rgba(cr, 0, 0, 1, .40);
    cairo_fill(cr);

    cairo_destroy(cr);

    //
    QPainter p(this);
    p.drawImage(0, 0, image);
  }
};

int main(int argc, char* argv[])
{
  QApplication app(argc, argv);

  CairoWidget w;
  w.show();

  return app.exec();
}

你可以尝试其他的黑科技,比如直接绘制到后备存储中,或者从自己的缓冲区初始化QImage,这对于一个自定义cairoQWidget来说是更好的选择:

QImage::QImage(const uchar *data, int width, int height, int bytesPerLine, QImage::Format format, QImageCleanupFunction cleanupFunction = nullptr, void *cleanupInfo = nullptr)

1
这可以通过以下不太好的方法实现:
  1. 创建一个cairo图像表面,绘制在该表面上。
  2. 调用cairo_image_surface_get_data()以获取像素。
  3. 将图像复制到Qt小部件中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接