QT无边框设计时,要进行拖拽窗体一般有两种方法:
目录
- 方案1:重写鼠标函数
- 方案2:使用qt_windows.h头文件
方案1:重写鼠标函数
该方案是常规写法,
重写鼠标点击函数mousePressEvent :获取窗体坐标点、鼠标坐标点;
重写鼠标移动函数mouseMoveEvent:获取最终鼠标点,移动窗口
下面是Demo类
mainwidget .h文件:
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
#include <QWidget>
#include <QMouseEvent>
#include <QPoint>
class MainWidget : public QWidget
{
Q_OBJECT
public:
MainWidget(QWidget *parent = nullptr);
~MainWidget();
void mousePressEvent(QMouseEvent* event) override;//重写鼠标按键事件
void mouseMoveEvent(QMouseEvent* event) override;//重写鼠标移动事件
private:
QPoint m_diff_pos;//鼠标和窗口的相对位移
QPoint m_window_pos;//窗口左上角点的位置
QPoint m_mouse_pos;//鼠标绝对位置
};
#endif // MAINWIDGET_H
mainwidget .cpp文件:
#include "mainwidget.h"
MainWidget::MainWidget(QWidget *parent)
: QWidget(parent)
{
this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowMinMaxButtonsHint);//设置无边框窗口
}
MainWidget::~MainWidget()
{
}
void MainWidget::mousePressEvent(QMouseEvent *event)
{
//鼠标刚点击的时候,求出相对位置
m_mouse_pos = event->globalPos();
m_window_pos = this->pos();
m_diff_pos = m_mouse_pos - m_window_pos;
}
void MainWidget::mouseMoveEvent(QMouseEvent *event)
{//鼠标移动后
QPoint pos = event->globalPos();//获取鼠标移动后的全局位置
// this->move(pos);//直接这么移动会产生跳跃感
this->move(pos - m_diff_pos);//鼠标位置减去相对距离
}
测试主函数
main.cpp
#include "mainwidget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWidget w;
w.show();
return a.exec();
}
方案2:使用qt_windows.h头文件
该方案依赖window系统头文件和内置库,特点是代码简单
移动窗体主要在mousePressEvent函数的重构上
void CTitleBar::mousePressEvent(QMouseEvent* event)
{//菜单栏可以拖拽整个窗口,这种写法依赖Windows的头文件及库,#include <qt_windows.h>
if(ReleaseCapture())
{
QWidget* pWindow = this->window();//获取主窗口
if(pWindow->isTopLevel())
{
SendMessage(HWND(pWindow->winId()),WM_SYSCOMMAND,SC_MOVE+HTCAPTION,0);
}
}
}
下面是个标题类的完整写法:
ctitlebar.h文件
#ifndef CTITLEBAR_H
#define CTITLEBAR_H
#include <QObject>
#include <QWidget>
#include <QLabel>
#include <QPushButton>
#include <QMouseEvent>
#include <qt_windows.h>//鼠标按下,拖拽窗口的写法
#pragma comment(lib,"user32.lib")
class CTitleBar:public QWidget
{
Q_OBJECT
public:
CTitleBar(QWidget* p = nullptr);
~CTitleBar();
private:
QLabel * m_pLogo= nullptr;//标题栏的logo
QLabel* m_ptitleTextlabel= nullptr;//标题栏名字
QPushButton* m_pSetBtn= nullptr;//右上角设置按钮
QPushButton* m_pMinBtn= nullptr;//右上角最小化按钮
QPushButton* m_pMaxBtn= nullptr;//右上角最大化按钮
QPushButton* m_pCloseBtn= nullptr;//右上角关闭按钮
private:
void initUI();
private:
void mousePressEvent(QMouseEvent* event) override;//鼠标点击按钮,可实现移动主窗体
void mouseDoubleClickEvent(QMouseEvent* event) override;//鼠标双击标题的时候方法,双击的时候最大化或者回归到平常
private slots:
void onClicked();
signals:
void sig_close();//发射信号给主窗口,是否关闭
};
#endif // CTITLEBAR_H
ctitlebar.cpp文件
#include "ctitlebar.h"
#include<QHBoxLayout>
CTitleBar::CTitleBar(QWidget* p )
:QWidget(p)
{
initUI();
}
CTitleBar::~CTitleBar()
{
if(!m_pLogo)delete m_pLogo;
if(!m_ptitleTextlabel)delete m_ptitleTextlabel;
if(!m_pSetBtn)delete m_pSetBtn;
if(!m_pMinBtn)delete m_pMinBtn;
if(!m_pMaxBtn)delete m_pMaxBtn;
if(!m_pCloseBtn)delete m_pCloseBtn;
}
void CTitleBar::initUI()
{
setAttribute(Qt::WA_StyledBackground);//禁止父窗口影响子窗口样式
this->setFixedHeight(32+5*2);//设置标题大小
this->setStyleSheet("background-color:rgb(44,62,80)");//标题暗黑色 54,54,54
m_pLogo = new QLabel(this);
m_pLogo->setFixedSize(32,32);
m_pLogo->setStyleSheet("background-image:url(:/resources/titlebar/JX_32x32.png);border:none");
m_ptitleTextlabel = new QLabel(this);
m_ptitleTextlabel->setText(u8"标题名字");
m_ptitleTextlabel->setFixedWidth(120);
m_ptitleTextlabel->setStyleSheet("QLabel{font-family:Microsoft YaHei; \
font-size:18px; \
color:#BDC8E2;}");//background-color:rgb(54,54,54);
m_pSetBtn = new QPushButton(this);
m_pSetBtn->setFixedSize(32,32);
m_pSetBtn->setStyleSheet("QPushButton{background-image:url(:/resources/titlebar/set.svg);border:nong;} \
QPushButton:hover{background-color:rgb(99,99,99);background-image:url(:/resources/titlebar/set_hover.svg);border:none;}");
m_pMinBtn = new QPushButton(this);
m_pMinBtn->setFixedSize(32,32);
m_pMinBtn->setStyleSheet("QPushButton{background-image:url(:/resources/titlebar/min.svg);border:nong;} \
QPushButton:hover{background-color:rgb(99,99,99);background-image:url(:/resources/titlebar/min_hover.svg);border:none;}");
m_pMaxBtn = new QPushButton(this);
m_pMaxBtn->setFixedSize(32,32);
m_pMaxBtn->setStyleSheet("QPushButton{background-image:url(:/resources/titlebar/normal.svg);border:nong;} \
QPushButton:hover{background-color:rgb(99,99,99);background-image:url(:/resources/titlebar/normal_hover.svg);border:none;}");
m_pCloseBtn = new QPushButton(this);
m_pCloseBtn->setFixedSize(32,32);
m_pCloseBtn->setStyleSheet("QPushButton{background-image:url(:/resources/titlebar/close.svg);border:nong;} \
QPushButton:hover{background-color:rgb(232,17,35);background-image:url(:/resources/titlebar/close_hover.svg);border:none;}");
QHBoxLayout * pHlay = new QHBoxLayout(this);
pHlay->addWidget(m_pLogo);
pHlay->addWidget(m_ptitleTextlabel);
pHlay->addStretch();//增加弹簧
pHlay->addWidget(m_pSetBtn);
//方案1,通过QSpacerItem添加间距
// QSpacerItem* pSpacerItem1 = new QSpacerItem(18,20,QSizePolicy::Fixed,QSizePolicy::Fixed);
// pHlay->addSpacerItem(pSpacerItem1);//弹簧每次使用的时候都得new出来,不能重复使用,否则重复释放造成程序异常
//方案2,通过addSpacing添加间距
pHlay->addSpacing(10);
pHlay->addWidget(m_pMinBtn);
pHlay->addSpacing(10);
pHlay->addWidget(m_pMaxBtn);
pHlay->addSpacing(10);
pHlay->addWidget(m_pCloseBtn);
pHlay->setContentsMargins(5,5,5,5);
connect(m_pMinBtn,&QPushButton::clicked,this,&CTitleBar::onClicked);
connect(m_pMaxBtn,&QPushButton::clicked,this,&CTitleBar::onClicked);
connect(m_pCloseBtn,&QPushButton::clicked,this,&CTitleBar::onClicked);
connect(m_pSetBtn,&QPushButton::clicked,this,&CTitleBar::onClicked);
}
void CTitleBar::mousePressEvent(QMouseEvent* event)
{//菜单栏可以拖拽整个窗口,这种写法依赖Windows的头文件及库,#include <qt_windows.h>
if(ReleaseCapture())
{
QWidget* pWindow = this->window();//获取主窗口
if(pWindow->isTopLevel())
{
SendMessage(HWND(pWindow->winId()),WM_SYSCOMMAND,SC_MOVE+HTCAPTION,0);
}
}
}
void CTitleBar::mouseDoubleClickEvent(QMouseEvent *event)
{
m_pMaxBtn->click();//双击的时候就是最大化按钮点击一下
}
void CTitleBar::onClicked()
{//点击右上角设置、最大化、最小化、关闭按钮的响应槽函数
QPushButton *pButton = qobject_cast<QPushButton*> (sender());//拿到发送者
QWidget* pWindow = this->window();//拿到父窗口指针
if(pButton == m_pMinBtn)
{
pWindow->showMinimized();//父窗口最小化
}else if(pButton == m_pMaxBtn)
{
if(pWindow->isMaximized())
{//如果是最大化的时候,则恢复正常
pWindow->showNormal();
m_pMaxBtn->setStyleSheet("QPushButton{background-image:url(:/resources/titlebar/normal.svg);border:nong;} \
QPushButton:hover{background-color:rgb(99,99,99);background-image:url(:/resources/titlebar/normal_hover.svg);border:none;}");
}else
{//如果不是最大化的时候则进行最大化
pWindow->showMaximized();//父窗口最大化
//并且更改图标样式
m_pMaxBtn->setStyleSheet("QPushButton{background-image:url(:/resources/titlebar/max.svg);border:nong;} \
QPushButton:hover{background-color:rgb(99,99,99);background-image:url(:/resources/titlebar/max_hover.svg);border:none;}");
}
}
else if(pButton == m_pCloseBtn)
{
//pWindow->close();//父窗口关闭
//增加判断提醒,是否关闭主窗口,确认关闭后再关闭
emit sig_close();//发射关闭信号
}
// else if(pButton == m_pSetBtn)
// {
// //弹出自定义的设置窗口
// }
}