印刷QWidget的(渲染)GUI线程之外
我想render一个QWidget
一个QPrinter
设备上没有GUI阻塞:印刷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说:
尽管QObject的是reentran t,GUI类,特别是QWidget和它的所有子类都不可重入。它们只能从 主线程使用。如前所述,QCoreApplication :: exec()也必须是从该线程调用的 。
而且也:
在实践中,其他线程 比主线程使用GUI类的不可能很容易被周围通过把 耗时的操作在一个单独的工作线程工作,显示 屏幕上的结果,当工作线程是 完成
我修改Mandelbrot Example但t时的主线程这里没有什么可以在我的情况下显示在屏幕上。我的Widget应该呈现(耗时操作)并发送到打印机。
那么你对我的情况有什么想法吗?
如果小部件的paintEvent
没有做太多计算,那么将小部件渲染到QPicture
的速度会非常快。 A QPicture
只是所有画家要求的记录。然后,您可以在并行作业中的打印机上重播它们。
或者,您可以确保窗口小部件不会从主线程中使用(通过隐藏并且没有父窗口),然后可以从任何线程中调用render
。
对不起,太迟的回复。这里是基于'QPicture'的建议:http://pastebin.com/xGrj4Ykd但是打印结果很小&混乱:(创建'QPrinter'对象是主要问题,并且阻止了我的GUI是否有其他解决方法? – IMAN4K
您可以完全控制结果的缩放比例,按照您希望的方式缩放它:) –
1)它在哪里准确地阻止? 2)永远不能从非GUI线程触摸QWidget。 – peppe
@ peppe.1。从我们点击QPrintDialog打印按钮直到它被发送到打印机的位置。在网络打印机上,它大约需要1秒,MyWidget也不复杂 – IMAN4K
一种选择是修改'_widget'它不直接绘制,而是绘制成“QImage”,然后显示该图像。然后,您可以从该插槽中检索该图像,并将副本发送给打印图像的线程。 另一个选择是移动窗口部件的绘图代码到一个带有'QPainter'的类中,然后打印线程可以实例化该类的一个新对象,并使用它就像窗口部件一样。 –