我创建了一个键盘事件,如果按下键“ 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
}


如果我按2s键,输出将是“ 2,2”而不是“ 1,2”。这意味着QTimer::singleShot不起作用。当我如此快速地按下按键时,我该怎么做才能获得真实的值。

最佳答案

a()插槽仅在插槽运行时输出g的当前值。如果您在实际发射第一张照片之前按了两个键,这将导致通过第一个输出发生之前的键释放事件功能将g增大两次。

实际上,如果您在最初的两秒钟内全力以赴并按了314159次键,您将看到输出的大量314159值。

一种方法可能是将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();
}


运行此代码,您将了解发生了什么:

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

09-12 11:30