a() 插槽仅在插槽运行时输出g 的当前值。如果您在第一个单发实际触发之前按下两个键, 这将导致g 被键释放事件函数之前增加两次 第一个输出已经发生。
事实上,如果你在最初的两秒内全力以赴并按下一个键 314159 次,你会看到大量的 314159 值输出。
一种方法可能是将g 的更新推迟到最后一刻,例如:
int g = 0;
void MainWindow::keyReleaseEvent(QKeyEvent *event) {
qtimer1->singleShot(2000, this, SLOT(a()));
}
a() {
qdebug << (++g);
}
虽然如果有一些 other 某处依赖于 g 的代码在原始点被更新,这将不起作用。
不幸的是,singleShot 生成了一个 timeout 事件,其中不包含任何附加信息。如果您需要额外的信息(例如修改时g的值),您可以在密钥释放事件中创建您的自己的线程,给它要存储为成员的当前值,然后启动线程 - 然后它会根据需要休眠并打印其存储的值而不是当前的g。
下面是一些示例代码,展示了这一点。 MyTask 代表您的按键释放事件函数,它启动一个单独的线程来管理时间和要打印的数据。每次它得到一个“事件”(在这种情况下是一个简单的循环,但在你的情况下,它将响应一个键被释放),它会启动一个线程,将g的当前值传递给它。线程对象存储 g 以供以后使用。
而且,一旦线程等待了合适的时间,它就会打印出 g 的存储值,而不管在此期间主任务对真正的 g 做了什么。
#include <QtCore>
#include <iostream>
class MyThread : public QThread
{
Q_OBJECT
public:
MyThread(int useGVal): m_gVal(useGVal) {}
public slots:
void run()
{
QThread::msleep(6000);
std::cout << QTime::currentTime().toString().toStdString()
<< " MyThread, g is " << m_gVal << std::endl;
}
private:
int m_gVal;
};
class MyTask : public QObject
{
Q_OBJECT
public:
MyTask(QObject *parent = 0) : QObject(parent) {}
public slots:
void run()
{
MyThread *x[5];
for (size_t i = 0; i < sizeof(x) / sizeof(*x); ++i)
{
std::cout << QTime::currentTime().toString().toStdString()
<< " MyTask, g <- " << ++g << std::endl;
x[i] = new MyThread(g);
x[i]->start();
QThread::msleep(1000);
}
for (int i = 0; i < 5; ++i)
{
x[i]->wait();
std::cout << QTime::currentTime().toString().toStdString()
<< " MyTask, thread #" << (i + 1) << " finished"
<< std::endl;
}
emit finished();
}
signals:
void finished();
private:
int g = 0;
};
#include "main.moc"
int main(int argc, char *argv[])
{
QCoreApplication appl(argc, argv);
MyTask *task = new MyTask(&appl);
QObject::connect(task, SIGNAL(finished()), &appl, SLOT(quit()));
QTimer::singleShot(0, task, SLOT(run()));
return appl.exec();
}
运行这段代码会告诉你发生了什么:
10:49:48 MyTask, g <- 1
10:49:49 MyTask, g <- 2
10:49:50 MyTask, g <- 3
10:49:51 MyTask, g <- 4
10:49:52 MyTask, g <- 5
10:49:54 MyThread, g is 1
10:49:54 MyTask, thread #1 finished
10:49:55 MyThread, g is 2
10:49:55 MyTask, thread #2 finished
10:49:56 MyThread, g is 3
10:49:56 MyTask, thread #3 finished
10:49:57 MyThread, g is 4
10:49:57 MyTask, thread #4 finished
10:49:58 MyThread, g is 5
10:49:58 MyTask, thread #5 finished