C++ 我怎样才能等到Qt中的keyevents中的每个进程都完成?
我创建了一个keyevent,如果我按下“a”键,它将执行函数a()。a()的过程将持续2秒。如果我像4次/2秒那样快速按键,我想等到每个过程完成。我测试发现,如果我在4次/2秒内按下该键,它将首先在以后的按键事件中执行该过程。我如何才能等到每个过程在keyevents中完成?我必须尝试使用线程和互斥。但有点不对劲。这是我第一次使用互斥。我不知道如何解决这个问题C++ 我怎样才能等到Qt中的keyevents中的每个进程都完成?,c++,qt,signals-slots,C++,Qt,Signals Slots,我创建了一个keyevent,如果我按下“a”键,它将执行函数a()。a()的过程将持续2秒。如果我像4次/2秒那样快速按键,我想等到每个过程完成。我测试发现,如果我在4次/2秒内按下该键,它将首先在以后的按键事件中执行该过程。我如何才能等到每个过程在keyevents中完成?我必须尝试使用线程和互斥。但有点不对劲。这是我第一次使用互斥。我不知道如何解决这个问题 int g = 0; void MainWindow::keyPressEvent(QKeyEvent *event) { int
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();
}
intg=0;
void主窗口::按键事件(QKeyEvent*事件)
{
int keyCode=事件->键();
if(keyCode==Qt::Key_A){
qDebug()开始();
}
}
void MyThread::run()//我试图在如此快速地按键的同时阻止第二次进程
{
互斥->锁();
…//进程:持续2秒
g++;
互斥->解锁();
}
不清楚需要什么:
- 如果要为每个按下的键启动线程,请使用
QtConcurrent::run(a)代码>内部没有任何互斥体
A()
- 如果要对每个按下的键执行
,但不能同时使用A()
QtConcurrent::run(A)代码>中有一个互斥体
(就像你做的那样)a()
context
的虚拟QObject
QObject*context=新的QObject代码>
thread
线程并运行
QThread*thread=newqthread{this};线程->开始()代码>
上下文
移动到线程
对象->移动到线程(线程)
main窗口中创建信号,比如runA()
李>
用A()连接此信号。
操作:
connect(这个,&MainWindow::runA,context,[](){A();})代码>
每次按下按钮“A”时,只需发出此信号:emit runA()代码>
每次发出信号时,将要执行的动作A(
)的事件发布到“线程事件循环”。所有事件将按发布顺序进行处理
#pragma一次
#包括
#包括
#包括
#包括
类主窗口:公共QWidget
{
Q_对象
私人:
QThread*线程;
QObject*上下文;
公众:
主窗口()
:线程{new QThread},
上下文{new QObject}
{
上下文->移动到线程(线程);
连接(this,&MainWindow::doAction,context,[this](){
动作();
});
线程->开始();
}
~main window(){
context->deleteLater();
thread->deleteLater();
}
信号:
无效动作();
公众:
无效按键事件(QKeyEvent*事件)
{
int keyCode=事件->键();
if(keyCode==Qt::Key_A){
发射doAction();
}
}
无效行动(){
qDebug()sleep(2);//模拟一些长时间的计算
}
};
无论你按“A”键多快。“正在执行操作。”将以恰好2秒的间隔打印,并精确显示按钮被按下的次数。一个快速解决方案是在只有一个线程的线程池上使用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"
//https://github.com/KubaO/stackoverflown/tree/master/questions/single-job-lambda-45913311
#包括
#包括
类日志窗口:公共QPlainTextEdit{
Q_对象
QThreadPool m_pool;
int g={};//只能从工作线程访问
无效密钥释放事件(QKeyEvent*事件)覆盖{
if(event->key()==Qt::key_A)
QtConcurrent::run(&m_-pool,this,&LogWindow::method);
QPlainTextEdit::keyReleaseEvent(事件);
}
///此方法必须是线程安全的。它永远不会重新输入。
void方法(){
QThread::sleep(2);//阻塞两秒钟
g++;
发射完成(g);
}
Q_信号无效完成(int);
公众:
LogWindow(QWidget*parent={}):QPlainTextEdit{parent}{
追加纯文本(“按下并释放“a”几次。\n”);
m_pool.setMaxThreadCount(1);
连接(this,&LogWindow::done,this,[this](int val){
追加纯文本(QString::number(val));
});
}
};
int main(int argc,字符**argv){
QApplication app{argc,argv};
对数窗口w;
w、 show();
返回app.exec();
}
#包括“main.moc”
你的线程应该做什么?我不明白你为什么需要一根线。只需维护已启动进程的计数器。使用流程完成时通知的信号。当你收到这样的信号时,减小计数器。当计数器达到0时,您将知道所有进程都已完成。虽然我不明白这一切有什么意义。如果你能稍微解释一下你的程序,那会很有帮助。我已经更新了代码。例如,我想更新a()中2s进程后g的值。但是,如果我这么快按下键,它就不会更新g并接收新的key事件,也不会从第一行再次执行execute A()。因此,我想设置一个互斥锁,以防止新事件发生,并确保它可以通过a()和更新g。但是代码不起作用。为什么要在启动进程两秒钟后更新g
?为什么不能立即更新?你应该更详细地解释你想要实现什么,因为现在它毫无意义。如果你想在进程运行时阻止一个keyevent,就在你的keyevent中。因为我已经设置了一个tim
// 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"