Reputation: 2418
In my project I need to generate thousands of unique QPixmap variables based on data collected.
This data is being collected in worker thread because it can be a little slow. At the end of the thread's work, it will create one big image containing all the little QPixmaps put together. However, QPixmaps can't be created and QPainter doesn't work in non GUI threads.
At first, I decided to do all QPixmap generation AFTER the thread already finished, however this is too slow. Converting the data into something that can be turned into a QPixmap takes just long enough to cause visible stuttering.
How can I generate QPixmaps from inside a worker thread so that the program doesn't hiccup?
Thanks for your time.
EDIT: A small example was requested:
QImage image(8, 8, QImage::Format_ARGB32_Premultiplied);
image.fill(Qt::transparent);
QPainter p(&image);
for(int x=0; x<16; x+=2)
{
for(int z=0; z<16; z+=2)
{
quint16 id = blockData[0][x][z];
quint8 data = id/4096;
id = id-(data*4096);
p.setPen(QColor("#ff0000"));
p.drawPoint(x/2, z/2);
}
}
p.end();
chunkResponse->blocks = QPixmap::fromImage(image);
Output is:
QPainter::setPen: Painter not active
QPainter::drawPoints: Painter not active
QPainter::end: Painter not active, aborted
Upvotes: 3
Views: 1137
Reputation: 243897
You do not have to use QPixmap
, but QImage
, and at the end you use what you convert from QPixmap
to be sent through the signal:
#include <QtWidgets>
struct Chunk
{
QImage blocks;
QDateTime time;
};
Q_DECLARE_METATYPE(Chunk)
class Thread: public QThread{
Q_OBJECT
public:
using QThread::QThread;
~Thread() { quit(); wait();}
Q_SIGNAL void sendChunk(const Chunk &);
protected:
void run() override{
while (true) {
Chunk chunkResponse;
QImage image(128, 128, QImage::Format_ARGB32_Premultiplied);
image.fill(Qt::transparent);
QPainter p(&image);
for(int x=0; x<256; x+=2)
{
for(int z=0; z<256; z+=2)
{
QColor color(qrand() % 256, qrand() % 256, qrand() % 256);
p.setPen(color);
p.drawPoint(x/2, z/2);
}
}
p.end();
chunkResponse.blocks = image;
chunkResponse.time = QDateTime::currentDateTime();
Q_EMIT sendChunk(chunkResponse);
QThread::msleep(10);
}
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QLabel w;
w.setFixedSize(128, 128);
Thread thread;
QObject::connect(&thread, &Thread::sendChunk, [&](const Chunk & chunk){
w.setPixmap(QPixmap::fromImage(chunk.blocks));
qDebug()<<chunk.time.toString();
});
thread.start();
w.show();
return a.exec();
}
#include "main.moc"
Upvotes: 1