在 GUI 线程之外打印 QWidget(渲染)
Printing QWidget (render) outside of GUI thread
我正在尝试 render 在 QPrinter
设备上 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
。
我正在尝试 render 在 QPrinter
设备上 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
。