我创建了一个keyevent,如果我按下键#34; A"它将执行函数A()。A()的过程将持续2秒。我想等到每个过程完成,如果我按下这么快就像4次/ 2秒。我测试并发现如果我按下4次/ 2秒的键,它将首先在稍后的按键事件中执行该过程。我怎么能等到每个进程在keyevents中完成?我必须尝试使用线程和互斥。但是有些不对劲。这是我第一次使用互斥锁。我不知道如何解决这个问题。
int g = 0;
void MainWindow::keyPressEvent(QKeyEvent *event)
{
int keyCode = event->key();
if(keyCode == Qt::Key_A) {
qDebug() << "da";
a->start();
}
}
void MyThread::run()// i try to block the second time process while press the key so quickly
{
mutex->lock();
...//process:last for 2s
g++;
mutex->unlock();
}
答案 0 :(得分:0)
如果我理解正确,你可以按下按钮A上的想要动作A()。但是,您在单独的线程中执行操作A(),因为您不想阻止GUI线程并冻结UI。
如果你不想&#34;跳过&#34;按钮推动解决方案很简单:
QObject
的虚拟context
。 QObject* context = new QObject;
QThread
调用thread
。 QThread* thread = new QThread{ this }; thread->start(); ...
context
移至thread
object->moveToThread(thread)
。MainWindow
课程中创建信号,说runA()
。 A()
动作连接:connect(this, &MainWindow::runA, context, [] () { A(); });
emit runA();
每次发出信号时,要执行的动作事件A(
)都会被发送到“线程事件循环”。所有活动将按顺序处理。
#pragma once
#include <QThread>
#include <QDebug>
#include <QWidget>
#include <QKeyEvent>
class MainWindow : public QWidget
{
Q_OBJECT
private:
QThread* thread;
QObject* context;
public:
MainWindow()
: thread{ new QThread },
context{ new QObject }
{
context->moveToThread(thread);
connect(this, &MainWindow::doAction, context, [this] () {
Action();
});
thread->start();
}
~MainWindow() {
context->deleteLater();
thread->deleteLater();
}
signals:
void doAction();
public:
void keyPressEvent(QKeyEvent* event)
{
int keyCode = event->key();
if(keyCode == Qt::Key_A) {
emit doAction();
}
}
void Action() {
qDebug() << "Action is being executed.";
QThread::currentThread()->sleep(2); // imitate some long calculation
}
};
无论您多快按下按钮&#34; A&#34;。 &#34;正在执行行动。&#34;将以2秒的间隔打印,并且按下按钮的次数。
答案 1 :(得分:0)
一个快速的解决方案是在线程池中使用QtConcurrent::run
,其中只有一个线程。这使您无需管理线程的生命周期,这是一种昂贵的资源 - 例如它将在未使用一段时间后被处置以释放资源。
// https://github.com/KubaO/stackoverflown/tree/master/questions/single-job-lambda-45913311
#include <QtWidgets>
#include <QtConcurrent>
class LogWindow : public QPlainTextEdit {
Q_OBJECT
QThreadPool m_pool;
int g = {}; // can be accessed from the worker thread only
void keyReleaseEvent(QKeyEvent * event) override {
if (event->key() == Qt::Key_A)
QtConcurrent::run(&m_pool, this, &LogWindow::method);
QPlainTextEdit::keyReleaseEvent(event);
}
/// This method must be thread-safe. It is never reentered.
void method() {
QThread::sleep(2); // block for two seconds
g++;
emit done(g);
}
Q_SIGNAL void done(int);
public:
LogWindow(QWidget * parent = {}) : QPlainTextEdit{parent} {
appendPlainText("Press and release 'a' a few times.\n");
m_pool.setMaxThreadCount(1);
connect(this, &LogWindow::done, this, [this](int val){
appendPlainText(QString::number(val));
});
}
};
int main(int argc, char ** argv) {
QApplication app{argc, argv};
LogWindow w;
w.show();
return app.exec();
}
#include "main.moc"
答案 2 :(得分:-1)
目前尚不清楚需要什么:
QtConcurrent::run(A);
启动一个主题,而A()
A()
但不能同时使用QtConcurrent::run(A);
A()
内的互斥锁(就像您所做的那样)