Qt跨线程操作QGraphicsView的种种坑和解决办法

34 篇文章 0 订阅

项目场景:

提示:这里简述项目相关背景:

Windows上用QGraphicsView显示大量图片,并进行走马灯式的展示


问题描述:

用MSVC2019编译会显示不出图片

解决方案:

换MinGW编译

====================================================

问题描述:

自己new的glWidget当图很大时只会显示黑色

// OpenGL
// 自己new的glWidget当图很大时只会显示黑色

// ui->gvl->setViewport(new QGLWidget(QGLFormat(QGL::Rgba)));
// ui->gvm->setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
// ui->gvr->setViewport(new QGLWidget(QGLFormat(QGL::SingleBuffer)));

解决方案:

用QOpenGLWidget,别用QGLWidget

// 但用控件的glWidget可以绘很大的图
// 用OpenGL很占内存,40节车厢用掉将近3G内存,不用OpenGL反而只用了100多M

// ui->gvl->setViewport(ui->gll);
// ui->gvm->setViewport(ui->glm);
// ui->gvr->setViewport(ui->glr);

====================================================

问题描述:

子线程中创建QGraphicsScene会导致啥也不显示

// // 啥也不显示,看来只能在UI线程中初始化
// this->m_spScene_l.reset(new QGraphicsScene(this));
// this->m_spScene_m.reset(new QGraphicsScene(this));
// this->m_spScene_r.reset(new QGraphicsScene(this));

解决方案:

只能在UI线程中创建QGraphicsScene

====================================================

问题描述:

子线程中直接添加QGraphicsItem会导致RtlReAllocateHeap失败的异常,猜想是线程冲突导致

解决方案:

    // 先禁止控件自动更新,在添加新单元,否则可能会导致RtlReAllocateHeap失败的异常,
    // 猜想是线程冲突导致,所以先禁止ui线程操作
    ui->gvl->setUpdatesEnabled(false);
    ui->gvm->setUpdatesEnabled(false);
    ui->gvr->setUpdatesEnabled(false);

    this->m_spScene_l->addItem(iteml);
    cout << "l" << endl;
    this->m_spScene_m->addItem(itemm);
    cout << "m" << endl;
    this->m_spScene_r->addItem(itemr);
    cout << "r" << endl;

    ui->gvl->setUpdatesEnabled(true);
    ui->gvm->setUpdatesEnabled(true);
    ui->gvr->setUpdatesEnabled(true);

====================================================

问题描述:

怎么刷新都不显示,一片空白

解决方案:

用QGraphicsView的setTransform方法设置不等于1倍的缩放,可以将添加的item们显示出来。

QTransform matrix;
matrix.scale(rScale / 1, rScale / 1);
ui->gvl->setTransform(matrix);
ui->gvm->setTransform(matrix);
ui->gvr->setTransform(matrix);

====================================================

问题描述:

只显示一部分item内容,其他的显示不出来

解决方案:

    // 就这个好使,能强制刷新
    this->m_spScene_l->update(iteml1->pos().x(),
                              iteml1->pos().y(),
                              iteml1->boundingRect().width(),
                              iteml1->boundingRect().height());
    this->m_spScene_m->update(itemm1->pos().x(),
                              itemm1->pos().y(),
                              itemm1->boundingRect().width(),
                              itemm1->boundingRect().height());
    this->m_spScene_r->update(itemr1->pos().x(),
                              itemr1->pos().y(),
                              itemr1->boundingRect().width(),
                              itemr1->boundingRect().height());
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt中,图形视图(QGraphicsView)是一个 QWidget 子类,它用于显示和编辑2D图形项。当您将 QGraphicsView 放置在单独的线程中时,您需要确保在主线程中更新场景。这是因为 Qt 图形系统本质上是单线程的,即只有在主线程中才能进行 GUI 更新。 您可以使用信号和槽机制将图像传递到主线程并更新场景。具体来说,您可以在子线程中发出一个信号,当信号在主线程中接收到时,您可以将图像添加到场景中并更新 QGraphicsView。以下是一个示例代码: ``` class MyThread : public QThread { Q_OBJECT signals: void sendImage(QImage image); protected: void run() override { // Load image in this thread QImage image("image.jpg"); emit sendImage(image); } }; class MyWidget : public QWidget { Q_OBJECT public: MyWidget(QWidget *parent = nullptr) : QWidget(parent) { // Create QGraphicsView and QGraphicsScene view = new QGraphicsView(this); scene = new QGraphicsScene(this); view->setScene(scene); // Connect signal to slot connect(this, &MyWidget::imageReceived, this, &MyWidget::updateScene); } private slots: void updateScene(QImage image) { // Add image to scene and update view QPixmap pixmap = QPixmap::fromImage(image); scene->addPixmap(pixmap); view->fitInView(scene->sceneRect(), Qt::KeepAspectRatio); } private: QGraphicsView *view; QGraphicsScene *scene; signals: void imageReceived(QImage image); }; int main(int argc, char *argv[]) { QApplication a(argc, argv); MyWidget w; w.show(); // Start worker thread MyThread thread; thread.start(); // Connect thread signal to widget slot QObject::connect(&thread, &MyThread::sendImage, &w, &MyWidget::imageReceived); return a.exec(); } ``` 在上面的示例中,MyThread 类表示子线程,它加载图像并将其发送到主线程。MyWidget 类是一个 QWidget 子类,它包含 QGraphicsView 和 QGraphicsScene。它还具有一个名为 imageReceived 的槽,用于将接收到的图像添加到场景中并更新 QGraphicsView。在 main() 函数中,我们创建了 MyWidget 实例,并启动了 MyThread 实例。我们还使用 connect() 函数将 MyThread 的 sendImage 信号连接到 MyWidget 的 imageReceived 槽。 请注意,如果您频繁地向 QGraphicsView 添加图形项,则可能会降低性能。在这种情况下,您可以考虑仅在图像发生更改时更新 QGraphicsView
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值