QDockWidget中QGraphicsView通过MainWindow信号槽调用不显示图像问题排查
我来帮你排查这个问题,核心问题出在变量作用域和类成员的正确引用上,咱们一步一步拆解:
问题根源分析
先看你的IvConfDockWidget构造函数代码:
IvConfDockWidget::IvConfDockWidget(IView *parent) : QDockWidget(parent), ui(new Ui::IvConfDockWidget) { ui->setupUi(this); MyGraphicsView *zoomGraphicsView = new MyGraphicsView(); // 这里是局部变量! MyGraphicsScene *zoomScene = new MyGraphicsScene(); // 同样是局部变量! ui->zoomLayout->addWidget(zoomGraphicsView); QPixmap zoomPixmap = QPixmap("/home/mischa/logo.png"); QGraphicsPixmapItem *zoomPixmapItem = new QGraphicsPixmapItem(zoomPixmap); updateZoomWindowReceived(zoomPixmapItem); // 从MainWindow调用时无效 }
你在构造函数里创建的zoomGraphicsView和zoomScene是局部变量,函数执行完毕后就会离开作用域——虽然你把zoomGraphicsView添加到了布局,它的内存会被布局管理,但槽函数updateZoomWindowReceived里访问的zoomGraphicsView和zoomScene应该是你在类里声明的成员变量吧?这两个成员变量根本没有被赋值,还是空指针状态!
这就导致了:构造函数里直接调用槽函数时,用的是当前作用域内的局部变量,所以能正常工作;但从MainWindow发信号触发槽函数时,实际上是在调用空指针的方法,自然不会有任何图像显示的效果。
另外还要确认一个次要问题:MainWindow里创建的IvConfDockWidget实例是不是你实际显示在界面上的那个?如果代码里创建了多个实例,信号发到未显示的实例上,也会导致图像不显示,但咱们先解决核心的变量作用域问题。
解决方案
修改IvConfDockWidget的类定义,把
zoomGraphicsView和zoomScene声明为类的成员变量:
在IvConfDockWidget的头文件里添加:private: MyGraphicsView *zoomGraphicsView; MyGraphicsScene *zoomScene;调整构造函数代码,将局部变量改为成员变量赋值:
IvConfDockWidget::IvConfDockWidget(IView *parent) : QDockWidget(parent), ui(new Ui::IvConfDockWidget), zoomGraphicsView(nullptr), zoomScene(nullptr) { // 初始化成员变量 ui->setupUi(this); zoomGraphicsView = new MyGraphicsView(); // 赋值给成员变量 zoomScene = new MyGraphicsScene(); // 赋值给成员变量 ui->zoomLayout->addWidget(zoomGraphicsView); QPixmap zoomPixmap = QPixmap("/home/mischa/logo.png"); QGraphicsPixmapItem *zoomPixmapItem = new QGraphicsPixmapItem(zoomPixmap); // updateZoomWindowReceived(zoomPixmapItem); // 可注释掉,用信号触发测试 }检查信号槽连接与实例一致性:
确保MainWindow里创建的icdw是你实际添加到主窗口的实例,比如:// MainWindow中创建并添加dock widget IvConfDockWidget *icdw = new IvConfDockWidget(this); // 传入父窗口this addDockWidget(Qt::RightDockWidgetArea, icdw); // 一定要添加到主窗口显示 connect(this, &IView::updateZoomWindow, icdw, &IvConfDockWidget::updateZoomWindowReceived); // 触发信号 QPixmap zoomPixmap = QPixmap("/home/mischa/logo.png"); QGraphicsPixmapItem *newItem = new QGraphicsPixmapItem(zoomPixmap); emit updateZoomWindow(newItem);
这样修改后,槽函数就能正确访问到你创建的MyGraphicsView和MyGraphicsScene实例,信号触发时就能正常显示图像了。
内容的提问来源于stack exchange,提问作者Mischa Schirmer

