【发布时间】:2015-12-28 18:57:05
【问题描述】:
我目前想知道如何合理使用QObject::destroyed(QObject*)signal。
观察
我注意到QWidget 派生对象的处理方式略有不同。考虑以下小型独立和编译示例:
/* sscce.pro:
QT += core gui widgets
CONFIG += c++11
TARGET = sscce
TEMPLATE = app
SOURCES += main.cpp
*/
#include <QApplication>
#include <QPushButton>
#include <QTimer>
#include <QtDebug>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QPushButton *button = new QPushButton;
QObject::connect(button, &QPushButton::destroyed,
[=](QObject *o) { qDebug() << o; });
delete button;
QTimer *timer = new QTimer;
QObject::connect(timer, &QTimer::destroyed,
[=](QObject *o) { qDebug() << o; });
delete timer;
return app.exec();
}
这是它的输出:
QWidget(0x1e9e1e0) QObject(0x1e5c530)因此,据推测,信号是从QObject 的 d-tor 发出的,因此当为QTimer 调用插槽时,只剩下QObject 基址。但是,QWidget 的 d-tor 似乎被拦截了,因为它仍然从插槽中将自己标识为 QWidget。
还有问题
假设我们有一个计时器池,它在QList<QTimer *> 中组织了几个计时器:
struct Pool {
QTimer *getTimer() {
return timers.at(/* some clever logic here */);
}
QList<QTimer *> timers;
};
现在,粗心的用户可能会删除借给他/她的计时器。好吧,我们可以做出反应并简单地从列表中删除该计时器。插槽可以解决问题:
Pool::Pool() {
/* for each timer created */
connect(theTimer, SIGNAL(destroyed(QObject*),
this, SLOT(timerDestroyed(QObject*));
}
void Pool::timerDeleted(QObject *object) {
QTimer *theTimer = /* hrm. */
timers.removeOne(theTimer);
}
但是现在呢?人力资源管理系统。调用插槽时,QTimer 已经处于破坏状态并部分破坏 - 只有它的 QObject 基础仍然存在。所以我很拒绝qobject_cast<QTimer *>(object)。
为了解决这个问题,我可以想到以下技巧:
- 将
QObjects 存储在列表中。然后,每次使用列表中的项目时,我都必须沮丧。不过,这可以使用static_cast来完成,因为我知道列表中只有QTimers,所以不需要dynamic_cast或qobject_cast。 -
removeOne的原样使用iterator遍历列表,然后将每个QTimer项目直接与QObject进行比较。然后使用QList::erase之类的。 -
static_cast甚至reinterpret_castQObject到Qtimer。
我该怎么办?
谢谢你,圣诞快乐,新年快乐 :-)[*]
[*]:当这个问题完成后会清理它。
【问题讨论】:
标签: c++ qt signals-slots