首页 > 解决方案 > 在函数内部的 while 循环中使用 processEvents()

问题描述

我有一个插槽功能

    void MobilePlatform::slot_lineFollow(bool checked) 
    {
        while(checked){
            ...
            QCoreApplication::processEvents(); 
        }
        if(!checked){
            ....
        }
    }

此函数是从QCheckBox请求的函数,当按下复选框时,变量checked为真并进入 while 循环,当未按下复选框checked时,变量为false并从 while 循环中退出并进入 if块,这是正常的,但我不明白的是,为什么在下一步中去QcoreApplication::processEvents(),当它出去时,变量checked是真的。

知道为什么会发生这些吗?

提前致谢!

标签: c++qt

解决方案


你已经被重新进入事件循环的后果所困扰。现在你知道为什么这不是一个好主意了。永远不要阻塞在主线程中,永远不要重新进入事件循环。反转控制流以准确反映异步现实:

class MobilePlatform : public QWidget {
  Q_OBJECT
  using self = MobilePlatform;
  using base_class = QWidget;
  using spin_handler = void (self::*)();
  QBasicTimer m_spinTimer;
  ...

  Q_SIGNAL void spinSignal();
  void spin(spin_handler);
  void despin(spin_handler);
  void follower();
  Q_SLOT void slot_lineFollow(bool checked);
protected:
  void timerEvent(QTimerEvent *) override;
public:
  ...
};

void MobilePlatform::timerEvent(QTimerEvent *ev) {
  if (ev->timerId() == m_spinTimer.timerId())
    Q_EMIT spinSignal();
  else
    base_class::timerEvent(ev);
}

void MobilePlatform::spin(spin_handler handler) {
  if (!m_spinTimer.isActive())
    m_spinTimer.start(0, this);
  connect(this, &self::spinSignal, this, handler, Qt::UniqueConnection | Qt::DirectConnection);
  Q_ASSERT(m_spinTimer.isActive());
}

void MobilePlatform::despin(spin_handler handler) {
  static const auto signal = QMetaMethod::fromSignal(&self::spinSignal);
  Q_ASSERT(signal.isValid());
  disconnect(this, &self::spinSignal, this, handler);
  auto const hasHandlers = isSignalConnected(signal);
  if (!hasHandlers)
    m_spinTimer.stop();
  Q_ASSERT(m_spinTimer.isActive() == hasHandlers);
}

void MobilePlatform::follower() {
  /* code that runs when following */
  ...
}

void MobilePlatform::slot_lineFollow(bool checked) {
  if (checked()) {
    spin(&self::follower);
  } else {
    despin(&self::follower);
    ...
  }
}

推荐阅读