16

I want to use Cairo graphics library whith Qt, but I can't find any documenattion. I just want to make the GUI whith Qt and use Cairo for drawing graphics in a Qt window.

Thanks.

Andrei
  • 4,289
  • 4
  • 25
  • 23

5 Answers5

13

Starting from cairo 1.17.8, the Qt support will be removed upstream.

Old answer

Recent version of cairo supports Qt by allowing to draw to a surface created with cairo_qt_surface_create(QPainter *painter): you can inspect the relevant header file here. There's no documentation because this feature is still experimental and disabled by default (you should compile cairo yourself explicitely enabling the Qt support with configure --enable-qt.

ntd
  • 7,372
  • 1
  • 27
  • 44
  • I will surely try this, I really hope it work's because now I am trying GTK and It's not so good as Qt. – Andrei Oct 30 '09 at 10:07
  • 1
    If you are using C++ I think you'll be more comfortable by using the [C++ bindings](http://library.gnome.org/devel/gtkmm-tutorial/unstable/index-info.html.en), not plain GTK+ itsself. Qt and QPainter, GTK+ and cairo, gtkmm and cairomm and any valid mix... depending on what you want they are all valid options. – ntd Oct 30 '09 at 13:18
  • the cairo qt surface does not work (yet) with Qt6 and requires a minor fix to work with Qt5. – user1095108 Jul 20 '21 at 04:46
8

Qt's Paint System is a very good drawing library and is vector based. And it's already there. If you pick Qt as your GUI toolkit, it can't get any easier.

andref
  • 4,460
  • 32
  • 45
  • @amc That is not correct. Most paint devices are raster-based, but [there are vector devices too](http://qt-project.org/doc/qt-5/qpaintengine.html#Type-enum): for instance, [QPdfWriter](http://qt-project.org/doc/qt-5/qpdfwriter.html). The `QPainter` API itself is mostly comprised of vector-based operations. It's not simply a blitter. – andref Mar 25 '14 at 19:45
  • the answer is 100% right, if you can avoid it, don't use cairo in your Qt app. – user1095108 Jul 20 '21 at 04:42
4

Caveat: This is not going to be the answer you are looking for.

Are you sure you want this? To what end? Is this about writing a QPaintDevice based on Cairo? Qt has its own graphics primitives implemented and so does Cairo. The only reason I can see is that you don't want the a heavy layer of Qt interfere with your system (embedded?). It's like you are trying to use the DirectFB backend of Cairo -- but then there's stuff like Qt-on-DirectFB. However, note such an implementation is costly and not free without its own set of quarks such as library-interop issues, printing from this Cairo based context etc. I'd suggest you do a regular search on Google to figure if such efforts are/ever were underway and weigh the pros and cons very heavily before even attempting the same.

dirkgently
  • 108,024
  • 16
  • 131
  • 187
  • Thank's for the answer. I just want a simple graphics library and a GUI library that can work togheter very easly, and I don't want to use the GUI library functions for drawing, I like Cairo because it's simple to use and It's vector based. Maybe you can recomend me another GUI library. – Andrei Oct 28 '09 at 21:09
  • This is the part I don't understand, why don't you want to use Qt? Maybe, we can suggest an alternative then. Qt is more than GUI. Graphics libraries are at a lower level of abstraction than GUI libraries. IMHO, You are taking a step back. GTK+ is another such GUI library (with a Cairo backend). – dirkgently Oct 29 '09 at 03:48
  • I will try Qt graphic functions. I tried GTK but it's a pain to use in projects. – Andrei Oct 29 '09 at 09:11
  • Sometimes we write programs that are supposed to use Qt only for its in-house tools - and the rest is only cairo based. That is the reason why people may need to use cairo for painting in UI widgets made by qt. – Петър Петров Dec 17 '13 at 16:46
1

It can be achieved by this dirty way:

  1. Create an cairo image surface, draw on that surface.
  2. Call cairo_image_surface_get_data() to get the pixels.
  3. Copy the image to a Qt widget.
jiandingzhe
  • 1,881
  • 15
  • 35
1

Here is an example of how it might be done:

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

There are other hacks you might try to attempt, such as drawing directly into the backing store or you can also initialize QImage from your own buffer, which would be preferable for a custom cairo QWidget:

QImage::QImage(const uchar *data, int width, int height, int bytesPerLine, QImage::Format format, QImageCleanupFunction cleanupFunction = nullptr, void *cleanupInfo = nullptr)
user1095108
  • 14,119
  • 9
  • 58
  • 116