【问题标题】:Cairo and Qt integrationCairo 和 Qt 集成
【发布时间】:2010-12-11 00:37:52
【问题描述】:

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

谢谢。

【问题讨论】:

    标签: c++ qt integration cairo


    【解决方案1】:

    从cairo 1.17.8开始,Qt支持will be removed upstream

    旧答案

    最近版本的 cairo 支持 Qt,允许绘制到使用 cairo_qt_surface_create(QPainter *painter) 创建的表面:您可以检查相关的头文件 here。没有文档,因为此功能仍处于试验阶段且默认禁用(您应该自己编译 cairo,明确启用 Qt 支持 configure --enable-qt

    【讨论】:

    • 我一定会试试这个,我真的希望它能奏效,因为我现在正在尝试 GTK,它还不如 Qt。
    • 如果您使用 C++,我认为使用 C++ bindings 会更舒服,而不是普通的 GTK+ 本身。 Qt 和 QPainter、GTK+ 和 cairo、gtkmm 和 cairomm 以及任何有效的组合......取决于你想要什么,它们都是有效的选项。
    • cairo qt 表面(还)不能与 Qt6 一起使用,需要进行小修复才能与 Qt5 一起使用。
    【解决方案2】:

    Qt's Paint System 是一个非常好的绘图库,基于矢量的。它已经在那里了。如果您选择 Qt 作为您的 GUI 工具包,它就再简单不过了。

    【讨论】:

    • @amc 这是不正确的。大多数绘图设备都是基于光栅的,但there are vector devices too:例如QPdfWriterQPainter API 本身主要由基于向量的操作组成。这不仅仅是一个吹口哨。
    • 答案是 100% 正确,如果可以避免,请不要在 Qt 应用中使用 cairo。
    【解决方案3】:

    警告:这不是您要寻找的答案。

    你确定要这个吗?达到什么目的?这是关于写一个基于开罗的QPaintDevice 吗? Qt 实现了自己的图形基元,Cairo 也是如此。我能看到的唯一原因是您不希望 Qt 的沉重层干扰您的系统(嵌入式?)。就像您正在尝试使用 Cairo 的 DirectFB 后端——但是还有 Qt-on-DirectFB 之类的东西。但是,请注意,如果没有自己的一组夸克(例如库互操作问题、从这个基于 Cairo 的上下文打印等),这种实现成本高昂且并非免费。我建议您在 Google 上进行定期搜索,以确定这些努力是否/曾经进行过并在尝试相同之前非常权衡利弊。

    【讨论】:

    • 感谢您的回答。我只想要一个简单的图形库和一个可以很容易地一起工作的 GUI 库,我不想使用 GUI 库函数进行绘图,我喜欢 Cairo,因为它使用简单并且基于矢量。也许你可以向我推荐另一个 GUI 库。
    • 这是我看不懂的部分,你为什么不想用Qt呢?也许,我们可以建议一个替代方案。 Qt 不仅仅是 GUI。图形库的抽象级别比 GUI 库低。恕我直言,您正在退后一步。 GTK+ 是另一个这样的 GUI 库(带有 Cairo 后端)。
    • 我会试试Qt的图形功能。我尝试了 GTK,但在项目中使用它很痛苦。
    • 有时我们编写的程序应该仅将 Qt 用于其内部工具 - 其余的仅基于 cairo。这就是为什么人们可能需要在 qt 制作的 UI 小部件中使用 cairo 进行绘画。
    【解决方案4】:

    可以通过这种肮脏的方式来实现:

    1. 创建一个 cairo 图像表面,在该表面上绘图。
    2. 调用 cairo_image_surface_get_data() 获取像素。
    3. 将图像复制到 Qt 小部件。

    【讨论】:

      【解决方案5】:

      这是一个如何完成的示例:

      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,这对于custom cairo QWidget 更可取:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-24
        • 2012-04-26
        • 2013-07-28
        • 2014-03-26
        • 1970-01-01
        • 2021-12-23
        相关资源
        最近更新 更多