在非GUI线程中生成QPixmap

时间:2018-04-02 23:22:50

标签: c++ multithreading qt qt5 qpixmap

在我的项目中,我需要根据收集的数据生成数千个独特的QPixmap变量。

这个数据正在工作线程中收集,因为它可能有点慢。在线程工作结束时,它将创建一个包含所有小QPixmaps的大图像。但是,无法创建QPixmaps,并且QPainter在非GUI线程中不起作用。

起初,我决定在线程已经完成之后执行所有QPixmap生成,但这太慢了。将数据转换为可以转换为QPixmap的内容需要足够长的时间才能导致明显的口吃。

如何从工作线程中生成QPixmaps,以便程序不会打嗝?

感谢您的时间。

编辑: 要求提供一个小例子:

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

输出是:

QPainter::setPen: Painter not active
QPainter::drawPoints: Painter not active
QPainter::end: Painter not active, aborted

1 个答案:

答案 0 :(得分:1)

您不必使用QPixmap,而是QImage,最后您使用从QPixmap转换的内容通过信号发送:

#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"