Cairo and Qt integration
Asked Answered
N

5

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.

Neveda answered 28/10, 2009 at 20:24 Comment(0)
S
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.

Shenashenan answered 29/10, 2009 at 23:52 Comment(3)
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.Neveda
If you are using C++ I think you'll be more comfortable by using the C++ bindings, 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.Shenashenan
the cairo qt surface does not work (yet) with Qt6 and requires a minor fix to work with Qt5.Slacks
L
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.

Labaw answered 29/10, 2009 at 2:3 Comment(2)
@amc That is not correct. Most paint devices are raster-based, but there are vector devices too: for instance, QPdfWriter. The QPainter API itself is mostly comprised of vector-based operations. It's not simply a blitter.Labaw
the answer is 100% right, if you can avoid it, don't use cairo in your Qt app.Slacks
H
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.

Hazan answered 28/10, 2009 at 20:57 Comment(4)
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.Neveda
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).Hazan
I will try Qt graphic functions. I tried GTK but it's a pain to use in projects.Neveda
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.Griskin
P
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.
Pershing answered 7/5, 2014 at 12:30 Comment(0)
S
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)
Slacks answered 13/5, 2021 at 20:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.