重复使用QTimer :: singleShot时鼠标锁定

时间:2013-04-10 20:21:02

标签: windows qt timer

我正在开发针对Windows 7的Qt 4.8.4 GUI应用程序。我试图实现"Solving a Problem Step by Step"方法以在长时间运行的计算期间保持GUI响应,这很好可以分成许多小步骤。

以下是此技术的最小工作示例:

Computation.h

#pragma once

#include "QtCore/QCoreApplication"
#include "QtCore/QDebug"
#include "QtCore/QObject"
#include "QtCore/QTimer"

class Computation : public QObject {
  Q_OBJECT
 public:
  Computation() : amount_(0) {}

 public Q_SLOTS:
  void start() {
    amount_ = 100000;
    QTimer::singleShot(0, this, SLOT(calculate()));
  }

 private Q_SLOTS:
  void calculate() {
    if (--amount_ > 0) {
      qDebug() << "Calculating..." << amount_;
      //QCoreApplication::processEvents();
      QTimer::singleShot(0, this, SLOT(calculate()));
    } else {
      qDebug() << "Finished";
    }
  }

 private:
  int amount_;
};

的main.cpp

#include "Computation.h"

#include "QtCore/QDebug"
#include "QtGui/QApplication"
#include "QtGui/QMainWindow"
#include "QtGui/QPushButton"

int main(int argc, char* argv[]) {
  QApplication app(argc, argv);

  Computation computation;

  QMainWindow window;
  QPushButton button(&window);
  button.setText("Test");
  QObject::connect(&button, SIGNAL(clicked()), &computation, SLOT(start()));

  window.show();
  return app.exec();
}

如果有人想要试用这个例子,还有一个CMakeLists.txt

现在,关于实际问题:当计算运行时,某些GUI交互会导致鼠标锁定。仍然可以移动光标,但在此状态下单击桌面的任何部分都不会产生任何影响。计算仍在继续。转义此锁定的唯一方法是使用键盘切换到另一个应用程序(例如Alt + Tab,按Windows键或Ctrl + Alt + Del)或等到计算结束。

导致此状态的GUI操作包括尝试移动或调整应用程序主窗口的大小。不是改变窗口的几何形状,而是发生上面解释的鼠标锁定。然而,一旦计算完成,窗口瞬间跳转到该位置应该被移动到(并且你没有切换到其间的另一个窗口)。

打开系统菜单(通过单击标题栏中的应用程序符号)也会导致类似的行为,但这次只有应用程序(包括系统菜单)对鼠标点击无动于衷。

我尝试通过在calculate()方法(上例中的注释行)中发出QCoreApplication::processEvents()来解决此问题。这只有一点帮助:不是每次时锁定鼠标,而是试图移动窗口或调整窗口大小,你现在必须做大约3-5次触发行为。 QCoreApplication::sendPostedEvents()QCoreApplication::flush()的不同组合也没有帮助。

我该如何解决这个问题?这是一个已知的Qt错误和/或是否有解决方法?

2 个答案:

答案 0 :(得分:0)

如果您需要使应用程序成为多线程,您可以使用Qt的插槽和信号架构。当事情发生变化时,只需从线程发出信号。然后在您的UI线程中,将一个插槽连接到您的线程中的信号: Qt: Background thread refreshing UI thread

答案 1 :(得分:0)

使用QThread绝对是一个比分块计算并尝试在一个线程中完成所有操作的更好的策略。

然后在计算线程中,每1/15秒使用一个计时器(例如)来调用已连接到主线程中的插槽的信号,这会通知UI更新您想要查看的任何数据计算。