1.目的
实现界面的无边框拉伸和移动
2.参考
【QT入门】 鼠标按下和移动事件实现无边框窗口拖动_qt 窗口拖动-CSDN博客
3.环境
qt6.7.0 ,qmake
4.实现原理
4.1.监听widget窗口的鼠标移动事件(即重写mouseMoveEvent方法)
该方法中实现判定当前鼠标的状态(上、下、左、右、左上、左下、右上、右下、可移动),可以使用枚举,点击后该重写方法不进行判定鼠标状态,转而判定当前该干啥。
4.2.监听mousePressEvent鼠标按下方法,获取当前鼠标在窗口中得到位置,保证移动后的窗口位置不变。
4.3.监听mouseReleaseEvent鼠标松开方法,清空点击位置
4.4.监听mouseDoubleClickEvent鼠标双击,个人需求,可不看,实现双击放大。
4.5.重写resizeEvent宽高改变,处理窗口变宽后元素发生变化。
4.6.实现moveCurrentWindow(私有创建的,不是重载的)方法移动窗口
4.7.实现drawCurrentWindow(私有创建的,不是重载的)方法拉伸窗口
实现代码
h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include<login_form.h>
#include<QSizeGrip>
QT_BEGIN_NAMESPACE
enum Location {
TOP,
BOTTOM,
LEFT,
RIGHT,
TOP_LEFT,
TOP_RIGHT,
BOTTOM_LEFT,
BOTTOM_RIGHT,
CENTER,
MOVE
};
namespace Ui {
class Widget;
}
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
virtual void mouseMoveEvent(QMouseEvent *event);
virtual void mousePressEvent(QMouseEvent *event);
//鼠标松开
virtual void mouseReleaseEvent(QMouseEvent *event);
//鼠标双击
virtual void mouseDoubleClickEvent(QMouseEvent *event);
QPoint z;
quint32 mouseClickY=0;//鼠标点击窗口时候鼠标距离窗口顶部位置
quint32 maxMouseClickY=30;//鼠标点击窗口时候鼠标距离窗口顶部位置 最大高度
// 当窗口大小改变时会自动调用这个函数
void resizeEvent(QResizeEvent *event) ;
void mouseStatus(QMouseEvent *event);//鼠标状态
void moveCurrentWindow(QMouseEvent *event);//移动窗口
void drawCurrentWindow(QMouseEvent *event);//拉伸当前窗口
private slots:
void on_main_top_close_clicked();
void on_main_top_reduce_clicked();
void on_main_top_amplify_clicked();
private:
Ui::Widget *ui;
Login_Form login;
Location location;//当前鼠标位置
int mouse_margin = 30;
QPoint windowZ;//鼠标相对于窗口的位置
QPoint topleft;//原来左上
QPoint bottomright;//原来右下
bool windowFlag=false;//当前状态,是否是点击的放大
};
#endif // WIDGET_H
cpp
#include "widget.h"
#include "ui_widget.h"
//鼠标拖拽
#include <qt_windows.h>
#include <windowsx.h>
#include <QWindow>
#include <windows.h>
#include <dwmapi.h>
#pragma comment(lib, "dwmapi.lib")
//
#define padding 10
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
this->setWindowFlags(this->windowFlags() | Qt::FramelessWindowHint); // 设置无边框
ui->setupUi(this);
login.show();
this->setWindowIcon(QIcon(":/tb")); // 网盘图标,替换为你的图标路径
connect(&login,&Login_Form::sendLogin,this,[=](QString uname){
qDebug()<<"登录账号==》"<<uname;
this->show();
login.close();
});
// // 添加 QSizeGrip 控件
// QSizeGrip *sizeGrip = new QSizeGrip(this);
// ui->gridLayout->addWidget(sizeGrip,0, Qt::AlignBottom | Qt::AlignRight);
this->setMouseTracking(true);//设置鼠标追踪,如果mouseMoveEvent还是必须点击使用的话那就在ui中设置mouseTracking这项(子集和父级都要设置,同时中间不能加布局)
}
Widget::~Widget()
{
delete ui;
}
//-->移动设置↓
void Widget::mouseMoveEvent(QMouseEvent *event)
{
QWidget::mouseMoveEvent(event);
if(!z.isNull()){
drawCurrentWindow(event);
return;//点击的时候不处理鼠标状态
}
mouseStatus(event);//设置鼠标状态
}
//点击时候获取当前位置
void Widget::mousePressEvent(QMouseEvent *event)
{
QWidget::mousePressEvent(event);
QPoint x = this->geometry().topLeft();//窗口左上角相对于左边左上角的位置,窗口位置
QPoint y = event->globalPos();//鼠标相对于座面左上角位置,鼠标全局
z = y-x;//定值,不变(鼠标距离窗口顶部和左边大小)
mouseClickY = z.ry();
QRect rect=this->rect();
}
//鼠标松开
void Widget::mouseReleaseEvent(QMouseEvent *event)
{
QWidget::mouseReleaseEvent(event);
// drawCurrentWindow(event);
z = QPoint();//清空点击
}
void Widget::mouseDoubleClickEvent(QMouseEvent *event)
{
qDebug()<<"鼠标双击了";
if(windowFlag){
qint32 minW = this->minimumSize().width();
qint32 minH = this->minimumSize().height();
this->resize(minW,minH);//外面的widget
QScreen *screen = QGuiApplication::primaryScreen ();
QRect screenRect = screen->availableVirtualGeometry();
qint32 pmW = screenRect.width();//屏幕w
qint32 pmH = screenRect.height();//屏幕h
qint32 x = (pmW - minW)/2;
qint32 y = (pmH - minH)/2;
this->move(x,y);
}else{
showMaximized();
}
windowFlag = !windowFlag;
}
//宽高发生变化
void Widget::resizeEvent(QResizeEvent *event)
{
quint32 xLength = this->size().width();
quint32 yLength = this->size().height();
// qDebug()<<"xLength="<<xLength;
// qDebug()<<"yLength="<<yLength;
//处理上面的缩小、关闭、放大按钮和长度
//处理长度
ui->main_top->resize(xLength,ui->main_top->height());
//处理按钮位置
quint32 buttonLength = 30;//按钮长度
ui->main_top_close->move(xLength-buttonLength*1, 0);
ui->main_top_amplify->move(xLength-buttonLength*2, 0);
ui->main_top_reduce->move(xLength-buttonLength*3, 0);
//处理第二个width
int cw1 = this->geometry().width();//当前宽
int ch1 = this->geometry().height();//当前高
ui->widget->resize(cw1,ch1-maxMouseClickY);//内部的widget
}
//鼠标状态
void Widget::mouseStatus(QMouseEvent *event)
{
QPoint windowX = this->geometry().topLeft();//窗口左上角相对于左边左上角的位置,窗口位置
QPoint windowY = event->globalPos();//鼠标相对于座面左上角位置,鼠标全局
QPoint windowZ = windowY-windowX;//定值,不变(鼠标距离窗口顶部和左边大小)
int x=windowZ.x();//x坐标
int y=windowZ.y();//y坐标
int currentWidth = this->geometry().width();//当前窗口宽度
int currentHeigth = this->geometry().height();//当前窗口高度
//移动窗口
if(x > padding && x < currentWidth- padding && y > padding&& y < maxMouseClickY){
location=MOVE;//移动
this->setCursor(QCursor(Qt::ArrowCursor));//鼠标变正常
}
//鼠标位于左上角
else if(x <= padding && y <= padding)
{
location=TOP_LEFT;
//这里鼠标光标变化
this->setCursor(QCursor(Qt::SizeFDiagCursor));
}
//鼠标位于左下角
else if(x<= padding && y>= currentHeigth - padding)
{
location=BOTTOM_LEFT;
this->setCursor(QCursor(Qt::SizeBDiagCursor));
}
//鼠标位于右上角
else if(x>= currentWidth - padding && y<= padding)
{
location=TOP_RIGHT;
this->setCursor(QCursor(Qt::SizeBDiagCursor));
}
//鼠标位于右下角
else if(x>= currentWidth - padding && y>= currentHeigth - padding)
{
location=BOTTOM_RIGHT;
this->setCursor(Qt::SizeFDiagCursor);
}
//鼠标位于上面
else if(y<=padding)
{
location=TOP;
this->setCursor(Qt::SizeVerCursor);
}
//鼠标位于左边
else if(x<=padding)
{
location=LEFT;
this->setCursor(Qt::SizeHorCursor);
}
//鼠标位于下面
else if(y>= currentHeigth - padding)
{
location=BOTTOM;
this->setCursor(Qt::SizeVerCursor);
}
//鼠标位于右边
else if(x>=currentWidth - padding)
{
location=RIGHT;
this->setCursor(Qt::SizeHorCursor);
}
//鼠标位于中间
else
{
location=CENTER;
this->setCursor(QCursor(Qt::ArrowCursor));
}
}
//移动窗口
void Widget::moveCurrentWindow(QMouseEvent *event)
{
QPoint y = event->globalPos();//鼠标相对于座面左上角位置
QPoint x = y - z;
this->move(x);
}
//拉伸窗口
void Widget::drawCurrentWindow(QMouseEvent *event)
{
//记录鼠标当前位置
QPoint globalpos=event->globalPos();
QRect rect=this->rect();
topleft=mapToGlobal(rect.topLeft());//左上角
bottomright=mapToGlobal(rect.bottomRight());//右下角
//创建一个矩形,并拉伸,最后设置其为窗口
QRect rmove(topleft,bottomright);
bool flag = true;
switch (location)
{
//上
case TOP:
//这里的if防止最小后窗口整体向下移动
if(bottomright.y()-globalpos.y()>this->minimumHeight())
rmove.setY(globalpos.y());
break;
//下
case BOTTOM:
rmove.setHeight(globalpos.y()-topleft.y());
break;
//左
case LEFT:
if(bottomright.x()-globalpos.x()>this->minimumWidth())
rmove.setX(globalpos.x());
break;
//右边
case RIGHT:
rmove.setWidth(globalpos.x()-topleft.x());
break;
//顶左
case TOP_LEFT:
if(bottomright.y()-globalpos.y()>this->minimumHeight()&&bottomright.x()-globalpos.x()>this->width())
{
rmove.setY(globalpos.y());
rmove.setX(globalpos.x());
}
break;
//顶右
case TOP_RIGHT:
if(bottomright.y()-globalpos.y()>this->minimumHeight())
{
rmove.setY(globalpos.y());
rmove.setWidth(globalpos.x()-topleft.x());
}
break;
//左下
case BOTTOM_LEFT:
if(bottomright.x()-globalpos.x()>this->width())
{
rmove.setHeight(globalpos.y()-topleft.y());
rmove.setX(globalpos.x());
}
break;
//右下
case BOTTOM_RIGHT:
rmove.setHeight(globalpos.y()-topleft.y());
rmove.setWidth(globalpos.x()-topleft.x());
break;
//移动
case MOVE:
{
moveCurrentWindow(event);//移动窗口
flag = false;
}
break;
//中间
case CENTER:
break;
}
//拉伸
if(flag){
//重新设置窗口几何形状(外面的和里面的)
this->setGeometry(rmove);//外面的widget
}
}
//-->移动设置↑
//关闭事件
void Widget::on_main_top_close_clicked()
{
close();
}
//最小化
void Widget::on_main_top_reduce_clicked()
{
showMinimized();
}
//最大化
void Widget::on_main_top_amplify_clicked()
{
showMaximized();
windowFlag = true;
}
ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Widget</class>
<widget class="QWidget" name="Widget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1000</width>
<height>640</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>1000</width>
<height>640</height>
</size>
</property>
<property name="mouseTracking">
<bool>true</bool>
</property>
<property name="windowTitle">
<string>Widget</string>
</property>
<property name="styleSheet">
<string notr="true">
background-color: rgb(255, 255, 255);
Widget#Widget{
}
border:1px solid black;</string>
</property>
<widget class="QWidget" name="main_top" native="true">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1000</width>
<height>30</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>1000</width>
<height>30</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>30</height>
</size>
</property>
<property name="mouseTracking">
<bool>true</bool>
</property>
<property name="styleSheet">
<string notr="true">QWidget#main_top{
border-top:1px solid rgb(179, 179, 179);
border-left:1px solid rgb(179, 179, 179);
border-right:1px solid rgb(179, 179, 179);
background-color: rgb(231, 231, 231);
}
</string>
</property>
<widget class="QPushButton" name="main_top_amplify">
<property name="geometry">
<rect>
<x>940</x>
<y>0</y>
<width>30</width>
<height>30</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="styleSheet">
<string notr="true">QPushButton#main_top_amplify:hover {
background-color: red;
}
QPushButton#main_top_amplify{
border-top:1px solid rgb(179, 179, 179);
color:white;
background-color: rgb(231, 231, 231);
}</string>
</property>
<property name="text">
<string>口</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
<widget class="QPushButton" name="main_top_reduce">
<property name="geometry">
<rect>
<x>910</x>
<y>0</y>
<width>30</width>
<height>30</height>
</rect>
</property>
<property name="palette">
<palette>
<active>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Button">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>231</red>
<green>231</green>
<blue>231</blue>
</color>
</brush>
</colorrole>
<colorrole role="Text">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="ButtonText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>231</red>
<green>231</green>
<blue>231</blue>
</color>
</brush>
</colorrole>
<colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>231</red>
<green>231</green>
<blue>231</blue>
</color>
</brush>
</colorrole>
<colorrole role="PlaceholderText">
<brush brushstyle="SolidPattern">
<color alpha="128">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Button">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>231</red>
<green>231</green>
<blue>231</blue>
</color>
</brush>
</colorrole>
<colorrole role="Text">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="ButtonText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>231</red>
<green>231</green>
<blue>231</blue>
</color>
</brush>
</colorrole>
<colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>231</red>
<green>231</green>
<blue>231</blue>
</color>
</brush>
</colorrole>
<colorrole role="PlaceholderText">
<brush brushstyle="SolidPattern">
<color alpha="128">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Button">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>231</red>
<green>231</green>
<blue>231</blue>
</color>
</brush>
</colorrole>
<colorrole role="Text">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="ButtonText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>231</red>
<green>231</green>
<blue>231</blue>
</color>
</brush>
</colorrole>
<colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>231</red>
<green>231</green>
<blue>231</blue>
</color>
</brush>
</colorrole>
<colorrole role="PlaceholderText">
<brush brushstyle="SolidPattern">
<color alpha="128">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="styleSheet">
<string notr="true">QPushButton#main_top_reduce:hover {
background-color: red;
}
QPushButton#main_top_reduce{
border-top:1px solid rgb(179, 179, 179);
color:white;
background-color: rgb(231, 231, 231);
}</string>
</property>
<property name="text">
<string>一</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
<widget class="QPushButton" name="main_top_close">
<property name="geometry">
<rect>
<x>970</x>
<y>0</y>
<width>30</width>
<height>30</height>
</rect>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="styleSheet">
<string notr="true">QPushButton#main_top_close:hover {
background-color: red;
}
QPushButton#main_top_close{
border-top:1px solid rgb(179, 179, 179);
border-right:1px solid rgb(179, 179, 179);
color:white;
background-color: rgb(231, 231, 231);
}</string>
</property>
<property name="text">
<string>x</string>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
<zorder>main_top_amplify</zorder>
<zorder>main_top_close</zorder>
<zorder>main_top_reduce</zorder>
</widget>
<widget class="QWidget" name="widget" native="true">
<property name="geometry">
<rect>
<x>0</x>
<y>30</y>
<width>1000</width>
<height>610</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>1000</width>
<height>610</height>
</size>
</property>
<property name="mouseTracking">
<bool>true</bool>
</property>
<property name="styleSheet">
<string notr="true">QWidget#widget{
border-bottom:1px solid rgb(179, 179, 179);
border-left:1px solid rgb(179, 179, 179);
border-right:1px solid rgb(179, 179, 179);
}</string>
</property>
</widget>
</widget>
<resources/>
<connections/>
</ui>