扁平窗口实现之无边框可拖拽控件
开发步骤
- QWidget去标题栏,变成无边框窗口
- 重写鼠标事件,实现可拖拽移动
QWidget去标题栏
这个步骤比较简单,调用setWindowFlag()
,然后设置Qt::FramelessWindowHint
枚举值就可以实现扁平化,当然,如果需要有很窗口状态需要设置可以使用setWindowFlags()
然后将多个枚举变量用|
将状态合并。
如果是自定义widget控件可以直接在初始化父类时直接在初始化列表中设置状态,代码如下:
// .h
namespace jq {
class JQFlatBase
: public QWidget {
public:
explicit JQFlatBase(QWidget* _parent = nullptr);
~JQFlatBase() override;
};
}
// .cpp
namespace jq {
JQFlatBase::~JQFlatBase() {
}
JQFlatBase::JQFlatBase(QWidget *_parent)
: QWidget(_parent, Qt::FramelessWindowHint){
}
}
可设置的状态标志有很多可以在帮助文档中搜索Qt::WindowType
查看,大致如下:
重写鼠标信号
没有标题栏的窗口是无法移动的因此需要进行重写鼠标事件,需要重写的鼠标事件包括:mousePressEvent(QMouseEvent *event)鼠标按下
、mouseReleaseEvent(QMouseEvent *event)鼠标松开
和mouseMoveEvent(QMouseEvent *event)鼠标移动
。
定义一个标志位变量在mousePressEvent(QMouseEvent *event)
和mouseReleaseEvent(QMouseEvent *event)
中记录是否鼠标左键被点击(一般是点中鼠标左键移动窗口)。
定义一个点变量在mousePressEvent(QMouseEvent *event)
中记录鼠标按下的位置。
结合标志位和记录的最后点击位置,在mouseMoveEvent(QMouseEvent *event)
中计算移动的距离,通过move(const QPoint &)
更新窗口位置,代码如下:
// .h
namespace jq {
class JQFlatBase
: public QWidget {
public:
explicit JQFlatBase(QWidget* _parent = nullptr);
~JQFlatBase() override;
protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
private:
bool is_mouse_press_;
QPoint last_mouse_point_;
};
}
// .cpp
namespace jq {
JQFlatBase::~JQFlatBase() {
}
JQFlatBase::JQFlatBase(QWidget *_parent)
: QWidget(_parent, Qt::FramelessWindowHint)
, is_mouse_press_(false)
, last_mouse_point_(0, 0) {
}
void JQFlatBase::mousePressEvent(QMouseEvent *event) {
if (event->button() != Qt::LeftButton) {
/* 不是鼠标左键则退出 */
return QWidget::mousePressEvent(event);
}
is_mouse_press_ = true;
last_mouse_point_ = event->pos();
}
void JQFlatBase::mouseReleaseEvent(QMouseEvent *event) {
if (event->button() != Qt::LeftButton) {
/* 不是鼠标左键则退出 */
return QWidget::mouseReleaseEvent(event);
}
is_mouse_press_ = false;
}
void JQFlatBase::mouseMoveEvent(QMouseEvent * event) {
if (is_mouse_press_)
move(event->pos() - last_mouse_point_ + pos());
else
return QWidget::mouseMoveEvent(event);
}
}
计算原理:
- 记录鼠标最后一次点击时,相对于
控件本身位置
点。 - 鼠标移动中计算
- 鼠标档期位置(相对控件本身) - 记录的点的位置 = 移动的距离
- 新窗口位置 = 移动的距离 + 当前窗口位置(使用控件本身的
pos()
函数获取)
由于都是相对于控件本身的位置做计算,因此,每次移动距离的点的计算结果基本是(±1~2, ±1~2)
。
件本身) - 记录的点的位置 = 移动的距离
- 新窗口位置 = 移动的距离 + 当前窗口位置(使用控件本身的
pos()
函数获取)
由于都是相对于控件本身的位置做计算,因此,每次移动距离的点的计算结果基本是(±1~2, ±1~2)
。