- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
虽然我通过 PyQt 从 Python 使用 Qt,这个问题同样适用于纯 Qt,只是语法有点不同,问题是一样的:
当我们想要在场景中处理 QGraphicsItem 对象时,我们调用 scene.removeItem(item)。当我们想在场景中处理 QGraphicsObject 对象时,我们调用 scene.removeItem(item) 因为它派生自 QGraphicsItem,但我们也调用 item.deleteLater() 因为它派生自 QObject,这是推荐的处理方式QObjects(以便正确处理进出项目的未决信号)。
问题是,由于 deleteLater() 的功能,对象项目中的槽可能会在项目从场景中移除后被调用。这要求我们测试 self.scene() 在插槽中是否为 None。但这很容易出错,因为很容易忘记这样做,如果调用插槽,忘记这一点会导致异常。
另一种方法是在从场景中移除项目之前不调用 deleteLater() ,但这需要手动断开项目与其他对象的连接。这与测试 self.scene() 在插槽中为 None 有类似的缺点,并且很容易忘记断开插槽。
减轻这种错误来源(如果没有隐藏的陷阱)的更好方法是当项目是 QGraphicsObject 时不调用 scene.removeItem(item),而只调用它的 deleteLater():它似乎,基于一些简单的测试,当项目最终被销毁时,场景会自动从其列表中删除项目。但是,我找不到任何说明这一点的 Qt 文档,我可能很幸运;也许在更现实的情况下,我会遇到内存泄漏或崩溃。
所以我倾向于在 item 是 QGraphicsObject 时调用 deleteLater() 而不调用 removeItem(),你认为这安全吗?
最佳答案
下面是QGraphicsItem
析构函数的源代码(取自qt-5.7/qtbase/src/widgets/graphicsview/qgraphicsitem.cpp)。如您所见,它执行了整个清理工作,并调用了场景的内部 removeItemHelper
函数(也由 removeItem
调用)。因此,它似乎设计得很好,可以通过删除来处理删除。
QGraphicsItem::~QGraphicsItem()
{
if (d_ptr->isObject) {
QGraphicsObject *o = static_cast<QGraphicsObject *>(this);
QObjectPrivate *p = QObjectPrivate::get(o);
p->wasDeleted = true;
if (p->declarativeData) {
if (static_cast<QAbstractDeclarativeDataImpl*>(p->declarativeData)->ownedByQml1) {
if (QAbstractDeclarativeData::destroyed_qml1)
QAbstractDeclarativeData::destroyed_qml1(p->declarativeData, o);
} else {
if (QAbstractDeclarativeData::destroyed)
QAbstractDeclarativeData::destroyed(p->declarativeData, o);
}
p->declarativeData = 0;
}
}
d_ptr->inDestructor = 1;
d_ptr->removeExtraItemCache();
#ifndef QT_NO_GESTURES
if (d_ptr->isObject && !d_ptr->gestureContext.isEmpty()) {
QGraphicsObject *o = static_cast<QGraphicsObject *>(this);
if (QGestureManager *manager = QGestureManager::instance()) {
const auto types = d_ptr->gestureContext.keys(); // FIXME: iterate over the map directly?
for (Qt::GestureType type : types)
manager->cleanupCachedGestures(o, type);
}
}
#endif
clearFocus();
setFocusProxy(0);
// Update focus scope item ptr.
QGraphicsItem *p = d_ptr->parent;
while (p) {
if (p->flags() & ItemIsFocusScope) {
if (p->d_ptr->focusScopeItem == this)
p->d_ptr->focusScopeItem = 0;
break;
}
p = p->d_ptr->parent;
}
if (!d_ptr->children.isEmpty()) {
while (!d_ptr->children.isEmpty())
delete d_ptr->children.first();
Q_ASSERT(d_ptr->children.isEmpty());
}
if (d_ptr->scene) {
d_ptr->scene->d_func()->removeItemHelper(this);
} else {
d_ptr->resetFocusProxy();
setParentItem(0);
}
#ifndef QT_NO_GRAPHICSEFFECT
delete d_ptr->graphicsEffect;
#endif //QT_NO_GRAPHICSEFFECT
if (d_ptr->transformData) {
for(int i = 0; i < d_ptr->transformData->graphicsTransforms.size(); ++i) {
QGraphicsTransform *t = d_ptr->transformData->graphicsTransforms.at(i);
static_cast<QGraphicsTransformPrivate *>(t->d_ptr.data())->item = 0;
delete t;
}
}
delete d_ptr->transformData;
if (QGraphicsItemCustomDataStore *dataStore = qt_dataStore())
dataStore->data.remove(this);
}
关于qt - QGraphicsObject 上的 deleteLater 与 removeItem,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41004665/
我无法弄清楚如何在 Qt 中缩放自定义子类 QGraphicsObject。我有代码工作,以便鼠标光标在悬停在边缘对象的 boundingRect(Left、Right、Top、Bottom) 上时发
在这个程序中,我有一个继承自 QGraphicsObject 的类。这个物体(马里奥)前进,后退并跳跃。对于这个工作,我改变了马里奥的坐标。但我有一个问题。我希望它在与砖 block 碰撞时停止。虽然
我正在 win7 上开发一个非常简单的应用程序并在 win8 上运行。当我在 win7 上运行时,它显示了由我的 QGraphicsObject 子类绘制的像素图。然而,当我将 exe 和 dll 复
我正在用 Qt 开发一个小游戏。我有一个板,其中每个字段都有一个指向单元的指针。在开始时,指针设置为 NULL。我想在搬家之前检查一下我单位周围的田地,但是 this->getRoom(-325,-3
我目前有一个基于 QGraphicsItem 的项目层次结构。 我想改为使用 QGraphicsObject,以便我可以在我的项目上放置属性。我不会使用信号/插槽或 QObject 的任何其他功能。
虽然我通过 PyQt 从 Python 使用 Qt,这个问题同样适用于纯 Qt,只是语法有点不同,问题是一样的: 当我们想要在场景中处理 QGraphicsItem 对象时,我们调用 scene.re
以下示例中,mouseMoveEvent 和 mousePressEvent 中的鼠标位置不同。这是由于增加的缩放而发生的。没有缩放,位置是相同的。 我是否必须根据更改后的缩放来更新boundingR
我已经创建了 Qt GUI 应用程序。它由 QGraphicsScene 组成,并且通过按下或触发 pushbutton 将项目(QGraphicsItem)添加到其中。添加到场景中的每个项目都是派生
情况:上层类 dialog 生成带有正方形的光栅。玩家坐在 (0,0) 处,当用户点击一个正方形时,寻路算法 pathFind 会生成玩家为达到此目标必须采取的方向的 QString。 QString
我的代码: //forkliftitem.h class ForkliftItem : public QGraphicsObject { Q_OBJECT //some necessa
我是一名优秀的程序员,十分优秀!