一、 内容简述
本文章主要介绍实现QPushButton在指定范围内可拖动,即像手机端的悬浮球那样,在手机可视单位内进行拖动,避免遮挡视线。
二、效果展示
本图片仅提供纯文字和纯图片的拖动按钮显示,当然这个类是继承于QPushButton的,也支持图文一起,图文的位置摆放可参考我的上一篇文章:QT基础使用1-QPushButton设置不同方向的图文
三、主要代码解析
实现代码拖拽的主要思想是,监听鼠标的事件,判断鼠标按钮,并获取鼠标的位移,判断位移是否在可移动范围内,然后将按钮移动过去。本文的按钮是继承于QPushButton的,重写监听事件,判断是否移动按钮。主要的监听代码如下
bool YDragButton::eventFilter(QObject *watched, QEvent *event)
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
switch(event->type())
{
case QEvent::MouseButtonPress:
{
//按钮按下,设置此时的状态是按下的,在鼠标移动的时候才会触发按钮移动事件
if (mouseEvent->button() == Qt::LeftButton) {
lastPoint = mouseEvent->pos();
isPressed = true;
}
break;
}
case QEvent::MouseMove:
{
//鼠标移动过程中,如果此时按钮是按下的状态,则可以判断移动按钮
if (isPressed) {
int dx = mouseEvent->pos().x() - lastPoint.x();
int dy = mouseEvent->pos().y() - lastPoint.y();
int x1 = this->x()+dx;
int y1 = this->y()+dy;
int right_distance = this->parentWidget()->width() -2*x_right_distancce-this->width();
int bottom_distance =this->parentWidget()->height() -2*y_bottom_distance -this->height();
if(x1>x_left_distance &&x1< right_distance &&y1>y_top_distance &&y1<bottom_distance)
this->move(this->x() + dx, this->y() + dy);
isMoved = true;
}
break;
}
case QEvent::MouseButtonRelease:
{
//按钮松开
if(isMoved !=true){
emit clicked();
emit toggled(!isChecked);
isChecked = !isChecked;
}else{
isMoved = false;
}
isPressed = false;
break;
}
case QEvent::MouseButtonDblClick:
//双击按钮
emit doubleClicked();
break;
default:
break;
}
return QWidget::eventFilter(watched,event);
}
四、完整的拖拽代码
YDragButton.h
#include <QWidget>
#include "qpainter.h"
#include "qevent.h"
#include "qtimer.h"
#include "qdebug.h"
#include <QPushButton>
class YDragButton : public QPushButton
{
Q_OBJECT
public:
explicit YDragButton(QWidget *parent = 0);
~YDragButton();
void setMargin(int left,int top,int right,int bottom);
signals:
void clicked();
void doubleClicked();
void toggled(bool isToggled);
protected:
bool eventFilter(QObject *watched, QEvent *event);
private:
QString text; //显示文字
bool isPressed; //鼠标是否按下
QPoint lastPoint; //鼠标按下最后坐标
QString type; //图片末尾类型
QString imgPath; //背景图片路径
QString imgName; //背景图片名称
int iconWidth =0 ; //图片宽度
int iconHeight =0; //图片高度
bool isMoved; //是否正在移动中
int x_left_distance; //可移动的距离左侧的距离
int y_top_distance; //可移动的距离上面的距离
int x_right_distancce; //可移动的距离右侧的距离
int y_bottom_distance; //可移动的距离上底部的距离
bool isChecked =false; //按钮的选中状态
};
YDragButton.cpp
/**
* 可拖动的按钮,作者qiong522 2023-06-26
* 1、设置图片型的
* 2、单独文字的可拖拽
* 3、可设置移动的区域的,即设置四周的距离
*/
YDragButton::YDragButton(QWidget *parent) : QPushButton(parent)
{
isPressed = false;
isMoved = false;
lastPoint = QPoint();
x_left_distance = 0;
x_right_distancce =0;
y_top_distance =0;
y_bottom_distance=0;
this->installEventFilter(this);
}
YDragButton::~YDragButton()
{
}
void YDragButton::setMargin(int left, int top, int right, int bottom)
{
x_left_distance = left;
y_top_distance = top;
x_right_distancce = right;
y_bottom_distance = bottom;
}
/** 识别鼠标绑定事件
* @brief YDragButton::eventFilter
* @param watched
* @param event
* @return
*/
bool YDragButton::eventFilter(QObject *watched, QEvent *event)
{
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
switch(event->type())
{
case QEvent::MouseButtonPress:
{
if (mouseEvent->button() == Qt::LeftButton) {
lastPoint = mouseEvent->pos();
isPressed = true;
}
break;
}
case QEvent::MouseMove:
{
if (isPressed) {
int dx = mouseEvent->pos().x() - lastPoint.x();
int dy = mouseEvent->pos().y() - lastPoint.y();
int x1 = this->x()+dx;
int y1 = this->y()+dy;
int right_distance = this->parentWidget()->width() -2*x_right_distancce-this->width();
int bottom_distance =this->parentWidget()->height() -2*y_bottom_distance -this->height();
if(x1>x_left_distance &&x1< right_distance &&y1>y_top_distance &&y1<bottom_distance)
this->move(this->x() + dx, this->y() + dy);
isMoved = true;
}
break;
}
case QEvent::MouseButtonRelease:
{
if(isMoved !=true){
emit clicked();
emit toggled(!isChecked);
isChecked = !isChecked;
}else{
isMoved = false;
}
isPressed = false;
break;
}
case QEvent::MouseButtonDblClick:
emit doubleClicked();
break;
default:
break;
}
return QWidget::eventFilter(watched,event);
}
按钮的调用
YDragButton *btn2 = new YDragButton(this);
btn2->setText("雪景");
btn2->setStyleSheet("background:transparent;font-size:50px,;color:red;");
btn2->setGeometry(50,50,100,100);
btn2->setMargin(0,0,0,0);