我想重复在SLOT中执行的操作,直到qpushbutton关闭。所以我已完成以下连接:
connect(ui->button,SIGNAL(pressed()),this,SLOT(button_hold()));
connect(ui->button,SIGNAL(released()),this,SLOT(button_released()));
我已按以下方式实施了SLOTS
void My_class::button_hold(){
//CLASS ATTRIBUTE key_is_released , i
QThread::msleep(200);
int wait_lock = 500;
i++; //GOAL OF THE SLOT
QCoreApplication::processEvents(QEventLoop::AllEvents);
while(!key_is_released){
QThread::msleep(wait_lock);
i++;
cout<<i<<endl;
if(wait_lock > 50) wait_lock -= 50;
QCoreApplication::processEvents(QEventLoop::AllEvents);
}
key_is_released = false;
}
void My_class::button_released(){
key_is_released = true;
}
目标是重复button_hod()插槽中的操作(在示例中,它是为了增加i),甚至更快地减少wait_lock并保持按钮按下。问题是,如果我单击按钮两次或更多次快速方式循环永远不会结束,就像processEvents()不起作用。如果只是点击按钮并且没有按下太长时间,则使用firts msleep以便不进入循环(我只增加一次) 。如果我没有快速点击,但我按下按钮,方法效果很好。
我做错了什么?
答案 0 :(得分:1)
重新进入事件循环是一个坏主意,并导致意大利面条代码。
Qt提供了一个具有UML语义的精彩状态机系统。通常最好对您设计为状态机的系统进行建模。这里有两种状态:空闲状态和活动状态:value
在激活时定期递增。
状态机将Ui细节(按钮)与核心功能分离:周期性递增值。
理想情况下,您还要将状态机和值分解为控制器类,并且仅将控制器和Ui从main()
或类似函数连接起来。
// https://github.com/KubaO/stackoverflown/tree/master/questions/48165864
#include <QtWidgets>
#include <type_traits>
class Ui : public QWidget {
Q_OBJECT
int m_value = -1;
QStateMachine m_machine{this};
QState m_idle{&m_machine}, m_active{&m_machine};
QVBoxLayout m_layout{this};
QPushButton m_button{"Hold Me"};
QLabel m_indicator;
QTimer m_timer;
void setValue(int val) {
if (m_value == val) return;
m_value = val;
m_indicator.setNum(m_value);
}
void step() {
if (m_value < std::numeric_limits<decltype(m_value)>::max())
setValue(m_value + 1);
}
public:
Ui(QWidget * parent = {}) : QWidget(parent) {
m_layout.addWidget(&m_button);
m_layout.addWidget(&m_indicator);
m_machine.setInitialState(&m_idle);
m_idle.addTransition(&m_button, &QPushButton::pressed, &m_active);
m_active.addTransition(&m_button, &QPushButton::released, &m_idle);
m_machine.start();
m_timer.setInterval(200);
connect(&m_timer, &QTimer::timeout, this, &Ui::step);
connect(&m_active, &QState::entered, [this]{
step();
m_timer.start();
});
connect(&m_active, &QState::exited, &m_timer, &QTimer::stop);
setValue(0);
}
};
int main(int argc, char ** argv) {
QApplication app{argc, argv};
Ui ui;
ui.show();
return app.exec();
}
#include "main.moc"
答案 1 :(得分:0)
问题在于快速点击10次,在进入循环之前,释放槽已被调用10次,因此key_is_released将永远不会再次更新为true。而且button_hold槽尚未被调用10次。然后添加一个计数器,在button_hold插槽中增加它并在释放槽中减少它,并在while循环中添加第二个条件计数器&gt; 0!key_is_released修复所有。(只有当并非所有释放槽都有时才进入循环已经运行了)