IMAN4K
IMAN4K

Reputation: 1345

Printing QWidget (render) outside of GUI thread

I'm trying to render a QWidget on a QPrinter device without GUI blocking :

My print method looks like this :

void MyClass::print() {
    QPrinter *printer = new QPrinter(QPrinter::HighResolution);
    printer->setPageSize(QPrinter::A5);
    printer->setPageOrientation(QPageLayout::Portrait);
    printer->setColorMode(QPrinter::Color);
    QPrintDialog *dialog = new QPrintDialog(printer);

    if (dialog->exec() == QDialog::Accepted) {
        MyWidget *_widget = new MyWidget( /* args */);

        QPainter *painter = new QPainter;
        painter->begin(printer);
        double xscale = printer->pageRect().width() / double(_widget ->width());
        double yscale = printer->pageRect().height() / double(_widget ->height());
        double scale = qMin(xscale, yscale);
        _widget ->setMinimumWidth((printer->pageRect().width() / scale));
        _widget ->setMinimumHeight(printer->pageRect().height() / scale);
        painter->translate(printer->paperRect().x() + printer->pageRect().width() / 2, printer->paperRect().y() + printer->pageRect().height() / 2);
        painter->scale(scale, scale);
        painter->translate(-_widget ->width() / 2, -_widget ->height() / 2);
        _widget ->render(painter);
        painter->end();
    }
    emit done();
}

With this function i have about 1-2 sec block state so i want to use QThread for this issue But Qt Doc says :

Although QObject is reentrant, the GUI classes, notably QWidget and all its subclasses, are not reentrant. They can only be used from the main thread. As noted earlier, QCoreApplication::exec() must also be called from that thread.

And also :

In practice, the impossibility of using GUI classes in other threads than the main thread can easily be worked around by putting time-consuming operations in a separate worker thread and displaying the results on screen in the main thread when the worker thread is finished

I've modified Mandelbrot Example but there is nothing to show on screen in my case. my Widget should be rendered (time-consuming operation) and sent to printer that's all.

So do you have anything in mind for my situation ?

Upvotes: 1

Views: 815

Answers (1)

If the widget's paintEvent doesn't do much computation, then it'll be very fast to render the widget to a QPicture. A QPicture is just a record of all painter calls. You can then replay them on a printer in a concurrent job.

Alternatively, you can ensure that the widget is not used from the main thread (by staying invisible and not having a parent), and then it's ok to call render from any thread.

Upvotes: 1

Related Questions