在一些应用场景如控制机器的Z轴升降,我们需要一个按钮能实现以下功能:
- 当你单次点击该按钮时,移动一段固定的距离。
- 当你在该按钮上一直按着鼠标不放时,则一直往一个方向移动,直到鼠标松开。
关键点
在实现该功能时,有两个关键点,分别如下:
- 当鼠标按下一个button时,先触发的是pressed信号,然后松开鼠标后触发released信号,接着才触发clicked信号。
- 如果启用QPushbutton的autoRepeat属性,同时设置autoRepeatDelay与autoRepeatInterval(eg:300,100),则鼠标一直按着不放时,pressed,released,clicked信号会一直依次循环触发。
设计思路
Z轴升降的移动控制接口一般都有两种,一种是在一个方向移动一段距离,另一种是一直单向移动,直到到达正/负限位停止。则可设计出Z轴的移动控制逻辑如下:
当用户按下移动按钮时,启用一个定时器,定时器超时后,判断是否已经触发按钮的released事件,如果已经触发,则判断当前事件为一个clicked事件;如果未触发,则判断为一个长按事件。clicked事件调用移动固定步长控制接口;长按事件调用单向移动控制接口,并在触发了released事件后调用停止移动接口。
代码
关键部分代码如下:
class CZaxisControl : public QMainWindow
{
Q_OBJECT
public:
void Init();
private slots :
void onReleaseBtn();
void onPressedBtn();
void onCheckMovingAction();
private:
Ui::CZaxisControl *m_ui;
bool m_is_pressing;
QTimer * m_moving_action_timer; // 定时器,设置超时,判断本次按下事件的类型
bool m_moving_flag; // true : have calling moving, false : have not calling moving
};
#define AUTO_REPEAT_DELAY 300
#define AUTO_REPEAT_INTERVAL 100
void CZaxisControl::Init()
{
connect(m_moving_action_timer, SIGNAL(timeout()), this, SLOT(onCheckMovingAction()));
}
void CZaxisControl::onReleaseBtn()
{
m_is_pressing = false;
m_moving_action_timer->stop();
if (m_moving_flag)
; // 调用停止移动接口,停止单向移动
if (!m_moving_flag)
{
;// 响应clicked,调用移动固定步长控制接口
}
m_moving_flag = false;
}
void CZaxisControl::onPressedBtn()
{
QObject *object = QObject::sender();
QPushButton *push_button = qobject_cast<QPushButton *>(object);
int obj_type;
QString object_name = push_button->objectName();
obj_type = object_name.toInt();
switch (obj_type)
{
case MovingType::Up_Fast:
; // 设置移动速度以及步长
break;
default:
return;
}
m_is_pressing = true;
// start up the moving action checking timer
m_moving_action_timer->start(AUTO_REPEAT_DELAY);
}
// checking the moving action : click or press
void CZaxisControl::onCheckMovingAction()
{
if (m_moving_flag)
return;
if (m_is_pressing) // still in pressing status, move to a direction
{
;// 调用单向移动控制接口
m_moving_flag = true;
}
}