在执行 buttonReleased() 之前等待 buttonPressed() 插槽完成
Wait for buttonPressed() slot to finish before executing buttonReleased()
我有一个 QPushButton,它对 pressed()
和 released()
信号执行冗长的操作。我如何确保在执行 buttonReleased()
插槽的操作之前完成 buttonPressed()
插槽的所有操作?
我已经尝试过使用 QMutex,但是在尝试锁定按钮释放时程序似乎陷入了无限循环,而互斥锁仍然被 buttonPressed()
函数锁定:
mymainwindow.h:
#include <QMutex>
// ...
QMutex mutex;
mymainwindow.cpp:
#include <QEventLoop>
#include <QTimer>
// ...
// In the main window constructor:
connect(myButton, SIGNAL(pressed()), this, SLOT(buttonPressed()));
connect(myButton, SIGNAL(released()), this, SLOT(buttonReleased()));
// ...
void MyMainWindow::buttonPressed()
{
mutex.lock();
// Here, I do the lengthy stuff, which is simulated by a loop
// that waits some time.
QEventLoop loop;
QTimer::singleShot(1000, &loop, SLOT(quit()));
loop.exec();
mutex.unlock();
}
void MyMainWindow::buttonReleased()
{
mutex.lock();
// ... (some stuff)
mutex.unlock();
}
是否需要连接释放您按钮的SLOT?您只需连接到 QEventLoop
的 destroyed()
SIGNAL 并调用 buttonReleased()
SLOT。
QEventLoop loop;
QTimer::singleShot(1000, &loop, SLOT(quit()));
connect(&loop, &QEventLoop::destroyed, this, &MyMainWindow::buttonReleased);
loop.exec();
编辑评论:
QEventLoop loop;
QTimer::singleShot(1000, &loop, SLOT(quit()));
connect(&loop, &QEventLoop::destroyed, [=] {
connect(myButton, &QPushButton::released, this, &MyMainWindow::buttonReleased);
});
loop.exec();
一般使用mutex是一种线程同步机制,这里不需要线程同步,因为是同一个线程。否则我会建议使用 QWaitCondition 等待 flag/mutex 改变(即表示你的条件现在可以了)。
在您的情况下,您可以在 "buttonPressed" 操作完成后发出一个信号(即当您的计时器结束时?)。如果 buttonPressed() 函数的结尾是您想要执行 buttonRelease() 函数的时间,那么您可以简单地使用 Qt::QueuedConnection 来确保事件的正确顺序(我通常不喜欢直接连接,因为它们的行为类似于函数调用(甚至中断 - 就像我认为发生在你身上的那样)。因此,以下更改可能会以一种简单的方式为你解决此问题:
// In the main window constructor:
connect(myButton, SIGNAL(pressed()), this, SLOT(buttonPressed()), Qt::QueuedConnection);
connect(myButton, SIGNAL(released()), this, SLOT(buttonReleased()), Qt::QueuedConnection);
我不确定执行你的事件循环到 "simulate" 你的 "long amount of time" 是否会工作......但是如果你做一些更像下面的事情来模拟你的长执行时间:
QElapsedTimer elapsedTime;
elapsedTime.start();
while (elapsedTime.elapsed() < 1000) // millisecs
{
// wait....
}
如果这不起作用,则只需在 buttonPressed() 结束时发出一个信号并在 buttonReleased() 中设置一个标志,这样:
void MyMainWindow::buttonPressed()
{
// actions here
emit buttonPressedDone();
}
void MyMainWindow::buttonReleased()
{
btnReleased = true;
}
void MyMainWindow::buttonPressedCompleted()
{
if (btnReleased )
{
// Do button released actions here
btnReleased = false;
}
// I am assuming that if the flag is not set then you don't want to do anything... but up to you...
}
并连接 buttonPressedDone --> buttonPressedCompleted
还有更多选项...这些只是您的几个选项...
我有一个 QPushButton,它对 pressed()
和 released()
信号执行冗长的操作。我如何确保在执行 buttonReleased()
插槽的操作之前完成 buttonPressed()
插槽的所有操作?
我已经尝试过使用 QMutex,但是在尝试锁定按钮释放时程序似乎陷入了无限循环,而互斥锁仍然被 buttonPressed()
函数锁定:
mymainwindow.h:
#include <QMutex>
// ...
QMutex mutex;
mymainwindow.cpp:
#include <QEventLoop>
#include <QTimer>
// ...
// In the main window constructor:
connect(myButton, SIGNAL(pressed()), this, SLOT(buttonPressed()));
connect(myButton, SIGNAL(released()), this, SLOT(buttonReleased()));
// ...
void MyMainWindow::buttonPressed()
{
mutex.lock();
// Here, I do the lengthy stuff, which is simulated by a loop
// that waits some time.
QEventLoop loop;
QTimer::singleShot(1000, &loop, SLOT(quit()));
loop.exec();
mutex.unlock();
}
void MyMainWindow::buttonReleased()
{
mutex.lock();
// ... (some stuff)
mutex.unlock();
}
是否需要连接释放您按钮的SLOT?您只需连接到 QEventLoop
的 destroyed()
SIGNAL 并调用 buttonReleased()
SLOT。
QEventLoop loop;
QTimer::singleShot(1000, &loop, SLOT(quit()));
connect(&loop, &QEventLoop::destroyed, this, &MyMainWindow::buttonReleased);
loop.exec();
编辑评论:
QEventLoop loop;
QTimer::singleShot(1000, &loop, SLOT(quit()));
connect(&loop, &QEventLoop::destroyed, [=] {
connect(myButton, &QPushButton::released, this, &MyMainWindow::buttonReleased);
});
loop.exec();
一般使用mutex是一种线程同步机制,这里不需要线程同步,因为是同一个线程。否则我会建议使用 QWaitCondition 等待 flag/mutex 改变(即表示你的条件现在可以了)。
在您的情况下,您可以在 "buttonPressed" 操作完成后发出一个信号(即当您的计时器结束时?)。如果 buttonPressed() 函数的结尾是您想要执行 buttonRelease() 函数的时间,那么您可以简单地使用 Qt::QueuedConnection 来确保事件的正确顺序(我通常不喜欢直接连接,因为它们的行为类似于函数调用(甚至中断 - 就像我认为发生在你身上的那样)。因此,以下更改可能会以一种简单的方式为你解决此问题:
// In the main window constructor:
connect(myButton, SIGNAL(pressed()), this, SLOT(buttonPressed()), Qt::QueuedConnection);
connect(myButton, SIGNAL(released()), this, SLOT(buttonReleased()), Qt::QueuedConnection);
我不确定执行你的事件循环到 "simulate" 你的 "long amount of time" 是否会工作......但是如果你做一些更像下面的事情来模拟你的长执行时间:
QElapsedTimer elapsedTime;
elapsedTime.start();
while (elapsedTime.elapsed() < 1000) // millisecs
{
// wait....
}
如果这不起作用,则只需在 buttonPressed() 结束时发出一个信号并在 buttonReleased() 中设置一个标志,这样:
void MyMainWindow::buttonPressed()
{
// actions here
emit buttonPressedDone();
}
void MyMainWindow::buttonReleased()
{
btnReleased = true;
}
void MyMainWindow::buttonPressedCompleted()
{
if (btnReleased )
{
// Do button released actions here
btnReleased = false;
}
// I am assuming that if the flag is not set then you don't want to do anything... but up to you...
}
并连接 buttonPressedDone --> buttonPressedCompleted
还有更多选项...这些只是您的几个选项...