c++ - Qt widget析构函数通过connected信号间接调用widget方法,并崩溃
问题描述
我基于 制作了一个小部件(QDataflowCanvas)QGraphicsView
,在其中将信号连接QGraphicsScene::selectionChanged()
到主窗口的插槽MainWindow::onSelectionChanged
:
void MainWindow::onSelectionChanged()
{
// canvas is ptr to QDataflowCanvas, subclass of QGraphicsView
auto selNodes = canvas->selectedNodes();
auto selConns = canvas->selectedConnections();
...
}
当我关闭我的MainWindow
并且在QGraphicsView
.
我认为我不需要提供完整的代码(尽管可以在此处找到),因为我已经隔离了崩溃的原因。
这就是将会发生的事情(按因果顺序):
- MainWindow 的析构函数被调用
- 调用 QDataflowCanvas 的析构函数
- 调用 QGraphicsView 的析构函数
- 调用 QGraphicsScene 的析构函数,触发删除所有项目(带
clear()
) - 调用 QGraphicsItem 的析构函数
- 这将触发 selectionChange 事件
- MainWindow::onSelectionChanged 插槽被调用
- 方法 QDataflowCanvas::selectedNodes() 被调用,但对象被销毁
- 碰撞!
从崩溃的堆栈跟踪中可以更详细地看到:
我找到了这个解决方法:如果我断开信号MainWindow::~MainWindow
,它当然不会崩溃:
MainWindow::~MainWindow()
{
QObject::disconnect(canvas->scene(), &QGraphicsScene::selectionChanged, this, &MainWindow::onSelectionChanged);
}
但这似乎是一种相当不典型的做法:我从来没有发现自己必须手动进行严重的信号槽连接,否则程序会崩溃。
必须有一个更合适的解决方案。
解决方案
canvas
我把它看得太简单了:) 只检查指针怎么样:
void MainWindow::onSelectionChanged()
{
if (!qobject_cast<QGraphicsScene*>(canvas))
return;
auto selNodes = canvas->selectedNodes();
auto selConns = canvas->selectedConnections();
...
}
我曾经qobject_cast
检查指针是否canvas
仍然存在。您可以以其他(更好的)方式进行检查。该代码有效。
推荐阅读
- python - 无法在 Django 的管理面板中查看添加屏幕
- angular - Waiting for dynamically generated Firebase list observables to finish
- omnet++ - 如何使用 OMNET++ 在路线上随机初始化车辆位置?
- ios - 无法在我的设备 xCode 上执行应用程序 - iOS
- java - 圆角mapbox mapView
- ios - 动画将新行插入 UITableView 中的新部分
- asp.net - 如何使用 vb.net/asp.net 中的搜索框在数据库中搜索内容
- html - 我的移动菜单导航栏没有关闭,它只打开
- jetbrains-ide - JB Rider 看不到更新的框架
- symfony - Symfony 创建自己的框架,自定义错误处理的具体例子