Qt测试当前对象/小部件的存在

时间:2016-11-22 18:20:56

标签: 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

有关

因此,如果我无法检查是否存在,如果对象被销毁,我该如何停止我的功能呢?析构函数中有什么东西?尝试捕捉(但我不喜欢)

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

编辑:代码结构:

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
    ...

}

2 个答案:

答案 0 :(得分:3)

您的问题是一种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());
}

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

第一次转型

  

在Qt中,我必须等待1秒才能让事件处理,所以我使用

不,你没有。您必须在经过一秒钟后运行代码。方法如下:

// 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);
}

第二次转型

  

我对对象进行操作(this-&gt; mListIP.currentItem();)

如果在该对象的上下文中运行functor / slot,则如果对象死亡,则不会执行functor / slot。因此:

// 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);
}

答案 1 :(得分:1)

如果需要指向QObject的安全指针,请使用QPointer。当对象被销毁时它将变为null。我们不清楚您的代码是如何构建的以及您尝试执行此操作的位置,但您也可以连接到对象&#34;销毁&#34;信号,并将其绑定到中止计时器的插槽,以便它不会尝试引用该对象。