在 GUI 线程之外打印 QWidget(渲染)

Printing QWidget (render) outside of GUI thread

我正在尝试 renderQPrinter 设备上 QWidget 没有 GUI 阻塞:

我的打印方法是这样的:

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

有了这个功能,我有大约 1-2 秒的块状态,所以我想使用 QThread 来解决这个问题但是 Qt Doc 说:

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.

还有:

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

我已经修改了 Mandelbrot Example,但在我的情况下屏幕上没有显示任何内容。我的 Widget 应该被渲染(耗时的操作)并发送到打印机,仅此而已。

那么你对我的情况有什么想法吗?

如果小部件的 paintEvent 不做太多计算,那么将小部件渲染为 QPicture 会非常快。一个QPicture只是所有painter calls的记录。然后您可以在打印机上并发作业中重播它们。

或者,您可以确保不从主线程使用小部件(通过保持不可见且没有父线程),然后可以从任何线程调用 render