c++ - Qt 测试当前对象/小部件是否存在

标签 c++ qt

在 Qt 中我必须等待 1 秒然后让事件处理所以我使用

QTime lDieTime= QTime::currentTime().addSecs(1);
while (QTime::currentTime() < lDieTime)
    QCoreApplication::processEvents(QEventLoop::AllEvents, 100);

但在这段时间之后,我对对象进行了操作(this->mListIP.currentItem();)

如果对象在 processEvents 期间未被销毁,则此方法可以正常工作。但是这个对象可以在这个循环中被销毁。

我如何测试小部件/对象是否仍然存在?

我已经尝试过 if(!this->isVisible()) 但它崩溃了(读取访问冲突),因为它不再存在了

我的问题与此有关 question

所以如果我不能检查它是否存在,如果对象被销毁我该如何停止我的函数?析构函数中的东西? try-catch(但我不喜欢那样)

注意:该函数由 QBasicTimer 的 timerEvent 每 2 秒调用一次

编辑:代码结构:

Class A (Widget)
   -constructor start a QBasicTimer of 2 seconds
   -timerEvent, called by the QBasicTimer every two seconds
Layout containing Class A can destroy Class A object

在 timerevent 中,我开始一个操作,等待 1 秒,然后尝试更新小部件。但是如果它被破坏了我就不能更新了

edit2 : 更多代码

void MaryAnnConnectionWidget::timerEvent( QTimerEvent * /*aEvent*/ )
{
    //operation base on a socket and a udp broadcast
    ...

    QTime lDieTime= QTime::currentTime().addSecs(1);
    while (QTime::currentTime() < lDieTime)
        QCoreApplication::processEvents(QEventLoop::AllEvents, 100);

    //Operation to handle answers from the broadcast
    ...

    if(this==nullptr) //Exit if we changed window <= CRASH HERE if widget destroyed
        return;

    //Handle the answers and displays results
    ...

}

最佳答案

您的问题是一种 XY 问题。您认为您的问题是关于如何跟踪对象的生命周期。一种解决方案是使用 QPointer 来做到这一点。另一个是不必显式跟踪它并让框架确保您的代码不会在不再存在的对象上运行。所以解决方案是互补的,但最好首先避免问题。下面我将解释如何操作。

假设您从以下可怕的代码开始。您必须将 doBefore()doAfter() 分解为独立方法:

void Class::timerEvent(QTimerEvent * ev) {
  if (ev->timerId() != m_timer.timerId()) return;
  doBefore();
  auto endTime = QTime::currentTime().addSecs(1);
  while (QTime::currentTime() < endTime)
    QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
  doAfter(mListIP.currentItem());
}

然后,通过对代码执行两次 转换就可以轻松解决您的顾虑。

第一次转换

In Qt I have to wait for 1 second and let event process so I use

不,你不知道。您必须在一秒钟后运行您的代码。方法如下:

// Qt 5

void Class::timerEvent(QTimerEvent * ev) {
  if (ev->timerId() != m_timer.timerId()) return;
  doBefore();
  QTimer::singleShot(1000, this, [this]{ doAfter(mListIP.currentItem()); });
}

// Qt 4

void Class::timerEvent(QTimerEvent * ev) {
  if (ev->timerId() != m_timer.timerId()) return;
  doBefore();
  m_currentItem = mListIP.currentItem()
  QTimer::singleShot(1000, this, SLOT(doAfterCurrent()));
}
void Class::doAfterCurrent() { // must be a slot
  doAfter(m_currentItem);
}

二次转化

I do operation on the object ( this->mListIP.currentItem();)

如果您在该对象的上下文中运行仿函数/槽,则当对象死亡时仿函数/槽将不会执行。因此:

// Qt 5

void Class::timerEvent(QTimerEvent * ev) {
  if (ev->timerId() != m_timer.timerId()) return;
  doBefore();
  auto item = mListIP.currentItem();
  Q_ASSERT(!item || this.findChildren<QObject*>().contains(item));
  //                       vvvv -- note the changed context!
  QTimer::singleShot(1000, item, [this,item]{ doAfter(item); });
}

// Qt 4

void Class::timerEvent(QTimerEvent * ev) {
  if (ev->timerId() != m_timer.timerId()) return;
  doBefore();
  m_currentItem = mListIP.currentItem();
  Q_ASSERT(!m_currentItem || this.findChildren<QObject*>().contains(m_currentItem));
  //                       vvvvvvvvvvvv -- note the changed context!
  QTimer::singleShot(1000, m_curentItem, SLOT(doAfterCurrent()));
}
void Class::doAfterCurrent() { // must be a slot
  doAfter(m_currentItem);
}

关于c++ - Qt 测试当前对象/小部件是否存在,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40748972/

相关文章:

c++ - 将枚举类传播到更高级别的类

qt - 关于在qt应用程序中编译openssl

qt - QML 表格 View : Number formatting

c++ - 修改 SFINAE 习语以使用 std::is_arithmetic 检查函数的返回类型

c++ - 疯狂的基本 C++ 错误

c++ - 创建 C++ 注册 QAbstractListModels 后,Qt 在关闭时崩溃

macos - OSX 上超大的 Qt 字体

c++ - 复制目录和子目录

c++ - IsNan vs value != 64 位 VS2010 上的值

c++ - C++ 中的内存黑客攻击/修改