gpt4 book ai didi

c++ - QTimer::singleShot 在 qkeyevent 中不起作用

转载 作者:行者123 更新时间:2023-11-28 01:44:07 28 4
gpt4 key购买 nike

我创建了一个键事件,如果我按下“A”键,它将执行函数 A()

在 A() 函数中,我将全局参数“g”递增 1 并创建一个 QTimer::singleShot 等待 2 秒并打印“g”的值。例如,“g”的初始值为0,当我按下“A”键两次时,“g”的输出值第一次应该是1,第二次应该是2。

但是,当我在 2 秒内按下按键时,我发现 QTimer::singleShot 第一次不起作用,输出是 "first:g=2,second :g=2"。为什么输出是"first:g=2,second:g=2"而不是"first:g=1,second:g=2"?还有为什么 QTimer::singleShot 第一次不工作,它只是同时打印值,没有等待 2s。

int g = 0;
void MainWindow::keyReleaseEvent(QKeyEvent *event) {
Qt::Key_A:
g++;
qtimer1->singleShot(2000, this, SLOT(a()));
}

//slots
a() {
qdebug << g;//print value
}

如果我在 2 秒内按下按键,输出是“2, 2”而不是“1,2”。这意味着 QTimer::singleShot 不起作用。当我如此快速地按下键时,我该如何获得真正的值(value)。

最佳答案

a() 槽仅在槽运行时输出 g 的当前值。如果您在第一个单次触发实际触发之前按下两个键,这将导致 g 两次被键释放事件函数之前递增em> 第一个输出发生了。

事实上,如果您全力以赴并在最初的两秒内按一个键一百次,您将看到大量 100 值输出。

一个可能的方法是将 g 的更新推迟到最后可能的时刻,例如:

int g = 0;
void MainWindow::keyReleaseEvent(QKeyEvent *event) {
qtimer1->singleShot(2000, this, SLOT(a()));
}
a() {
qdebug << (++g);
}

尽管如果某处有一些依赖于 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();
}

运行此代码会向您展示会发生什么。尽管主线程在工作线程开始使用它之前多次更新 g,但工作线程中使用的值是您期望的值(创建工作线程时存在的值):

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

关于c++ - QTimer::singleShot 在 qkeyevent 中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45910623/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com