QPrinter in QThread produce QPixmap error
-
Simple code example:
@void MainWindow::on_btnPrint_clicked()
{
QThread *thread = new QThread(this);
ThreadedPrint *print = new ThreadedPrint();
print->moveToThread(thread);
thread->start();
QMetaObject::invokeMethod(print, "print", Qt::QueuedConnection);
}ThreadedPrint::ThreadedPrint(QObject *parent) :
QObject(parent)
{
m_printer = new QPrinter(QPrinter::PrinterResolution);
m_printer->setPageSize(QPrinter::A4);
}void ThreadedPrint::print()
{
QPainter painter(m_printer);
QRect pageRect = m_printer->pageRect();
QImage image(pageRect.width(), pageRect.height(), QImage::Format_RGB32);
image.fill(Qt::black);
painter.drawImage(0, 0, image);
}
@
And i got:
QPixmap: It is not safe to use pixmaps outside the GUI thread
and I got empty page from my printer.
But when I use printing into PDF all works fine, so bug only appears when I try to print on real printer.The documentation states:
Painting in Threads
QPainter can be used in a thread to paint onto QImage, QPrinter, and QPicture paint devices.So my question is: can i print in non-gui thread?
-
The QPrinter instance allocated on the heap in your ThreadedPrint constructor will be in the main thread (and stay there).
So either:
- Make the QPrinter instance a member variable
- Put the heap allocation in a slot, called init() for example, and have that slot connected to the started() signal of the QThread wrapper object.
Here is an example Qt 4 program that works without issue here:
@
#include <QtGui>
#include <QDebug>class ThreadedPrint: public QObject {
Q_OBJECT
QPrinter *m_printer;
public:
ThreadedPrint(QObject *p = 0): QObject(p) {
m_printer = 0;
}
~ThreadedPrint() {
delete m_printer;
}signals:
void finished();public slots:
void init() {
qDebug() << Q_FUNC_INFO;
m_printer = new QPrinter;
}
void doPrint() {
qDebug() << Q_FUNC_INFO;
Q_ASSERT(m_printer);
QPainter painter(m_printer);
QRect pageRect = m_printer->pageRect();
QImage image(pageRect.width(), pageRect.height(), QImage::Format_RGB32);
image.fill(Qt::black);
painter.drawImage(0, 0, image);// wait a while then finish the thread QTimer::singleShot(3000, this, SIGNAL(finished())); }
};
int main(int argc, char **argv)
{
QApplication app(argc, argv);QThread *thread= new QThread(qApp); ThreadedPrint *worker = new ThreadedPrint; worker->moveToThread(thread); QObject::connect(thread, SIGNAL(started()), worker, SLOT(init())); QObject::connect(worker, SIGNAL(finished()), thread, SLOT(quit())); QObject::connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater())); QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); thread->start(); QTimer::singleShot(10000, qApp, SLOT(quit())); QTimer::singleShot(1000, worker, SLOT(doPrint())); return app.exec();
}
#include "main.moc"
@ -
Thanks for explanation, but I still have the same error...
Even when I create QPrinter object in doPrint slot.
-
The example code I posted works fine here. Does it fail for you?
-
Yes. I compile it without changes and get QPixmap error.
Qt 4.8.4, Windows 7 x32.