当前位置: 首页 > ai >正文

Qt 无边框窗口实现拖动与窗口控制(最小化/最大化/关闭)

在 Qt 中,使用 Qt::FramelessWindowHint 可以创建无边框窗口,但这样会导致窗口无法拖动,并且系统默认的标题栏按钮(最小化、最大化、关闭)也会消失。本文将介绍如何实现无边框窗口的鼠标拖动功能,并添加自定义最小化、最大化和关闭按钮


1. 设置无边框窗口

首先,在 MainWindow 的构造函数中移除默认边框:

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)
{ui->setupUi(this);// 设置无边框窗口setWindowFlags(Qt::FramelessWindowHint);// 连接按钮信号(最小化、最大化/还原、关闭)connect(ui->toolButton_minimize, &QToolButton::clicked, this, &MainWindow::showMinimized);connect(ui->toolButton_maximize, &QToolButton::clicked, this, [this]() {if (this->isMaximized()) {this->showNormal();  // 如果已最大化,则还原} else {this->showMaximized();  // 否则最大化}});connect(ui->toolButton_close, &QToolButton::clicked, this, &MainWindow::close);
}

这里:

  • toolButton_minimize 是最小化按钮
  • toolButton_maximize 是最大化/还原切换按钮
  • toolButton_close 是关闭按钮

2. 实现窗口拖动功能

由于无边框窗口无法拖动,我们需要手动处理鼠标事件:

  1. MainWindow 类中添加成员变量和重写鼠标事件
// MainWindow.h
protected:void mousePressEvent(QMouseEvent *event) override;void mouseMoveEvent(QMouseEvent *event) override;private:QPoint m_dragPosition;  // 记录鼠标按下时的位置
  1. 实现鼠标事件
// MainWindow.cpp
void MainWindow::mousePressEvent(QMouseEvent *event)
{if (event->button() == Qt::LeftButton) {m_dragPosition = event->globalPos() - frameGeometry().topLeft();event->accept();}QMainWindow::mousePressEvent(event);
}void MainWindow::mouseMoveEvent(QMouseEvent *event)
{if (event->buttons() & Qt::LeftButton) {move(event->globalPos() - m_dragPosition);  // 移动窗口event->accept();}QMainWindow::mouseMoveEvent(event);
}
  • mousePressEvent:当鼠标左键按下时,记录当前鼠标位置相对于窗口左上角的偏移量。
  • mouseMoveEvent:当鼠标左键按下并移动时,计算窗口新位置并移动窗口。

3. 完整代码示例

MainWindow.h

#include <QMainWindow>
#include <QMouseEvent>namespace Ui {
class MainWindow;
}class MainWindow : public QMainWindow
{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = nullptr);~MainWindow();protected:void mousePressEvent(QMouseEvent *event) override;void mouseMoveEvent(QMouseEvent *event) override;private:Ui::MainWindow *ui;QPoint m_dragPosition;
};

MainWindow.cpp

#include "MainWindow.h"
#include "ui_MainWindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);// 设置无边框窗口setWindowFlags(Qt::FramelessWindowHint);// 连接按钮信号connect(ui->toolButton_minimize, &QToolButton::clicked, this, &MainWindow::showMinimized);connect(ui->toolButton_maximize, &QToolButton::clicked, this, [this]() {if (this->isMaximized()) {this->showNormal();  // 还原} else {this->showMaximized();  // 最大化}});connect(ui->toolButton_close, &QToolButton::clicked, this, &MainWindow::close);
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::mousePressEvent(QMouseEvent *event)
{if (event->button() == Qt::LeftButton) {m_dragPosition = event->globalPos() - frameGeometry().topLeft();event->accept();}QMainWindow::mousePressEvent(event);
}void MainWindow::mouseMoveEvent(QMouseEvent *event)
{if (event->buttons() & Qt::LeftButton) {move(event->globalPos() - m_dragPosition);event->accept();}QMainWindow::mouseMoveEvent(event);
}

4. 效果

  • 窗口无边框,可以拖动。
  • 点击最小化按钮,窗口最小化到任务栏。
  • 点击最大化按钮,窗口全屏;再次点击还原。
  • 点击关闭按钮,窗口关闭。

5. 进阶优化

  1. 限制拖动区域
    如果只想让窗口的某个区域(如标题栏)可拖动,可以修改 mousePressEvent

    if (event->button() == Qt::LeftButton && ui->titleBarWidget->geometry().contains(event->pos())) {m_dragPosition = event->globalPos() - frameGeometry().topLeft();event->accept();
    }
    
  2. 双击最大化/还原
    可以重写 mouseDoubleClickEvent 实现双击标题栏最大化/还原。

  3. 窗口阴影效果
    使用 QGraphicsDropShadowEffect 让无边框窗口看起来更美观。


6. 总结

通过重写 mousePressEventmouseMoveEvent,我们可以实现无边框窗口的拖动功能。结合自定义按钮,可以完全替代系统默认的标题栏,打造更个性化的 UI。

http://www.xdnf.cn/news/9822.html

相关文章:

  • 从外卖APP到网络协议:深入解析UDP及应用层协议
  • [python] argparse怎么指定bool类型?
  • ST-GCN
  • 外地车在北京进京证用完后该如何行驶
  • Free2AI:企业智能化转型的加速器
  • 第七十篇 从餐厅后厨到电影院选座:生活场景拆解Java并发编程核心
  • Unity3D多场景管理框架设计
  • 可靠数据传输原理
  • 3.mkdir新建目录命令与touch新建文件命令
  • Executors工具类的潜在问题
  • Java 面试实录:从Spring到微服务的技术探讨
  • 仿真每日一练 | ABAQUS显式动力学分析——小球跌落
  • JVM——SubstrateVM:AOT编译框架
  • RS232/485转Profinet网关通讯气体检漏仪案例分享
  • Swift 解锁 LeetCode 热门难题:不改数组也能找出重复数字?
  • Nacos 配置管理案例:nacos-spring-cloud-config-example详解
  • IPD的基础理论与框架——(四)矩阵型组织:打破部门壁垒,构建高效协同的底层
  • django项目开启debug页面操作有数据操作记录
  • 首发支持! 基于昇腾MindIE玩转InternVL3多模态理解最新模型
  • 工具识别系统Python+深度学习+人工智能+卷积神经网络算法+TensorFlow+图像识别
  • ppt一键制作:ai自动生成PPT,便捷高效超级精美!
  • 全志F1c200开发笔记——移植Debian文件系统
  • 彻底卸载安装的虚拟机VMware Workstation软件
  • 树莓派超全系列教程文档--(51)如何使用SSH登录树莓派
  • RFID综合项目实训 | 基于C#的一卡通管理系统
  • AI绘画提示词:从零开始掌握Prompt Engineering的艺术
  • 群辉(synology)NAS老机器连接出现网页端可以进入,但是本地访问输入一样的账号密码是出现错误时解决方案
  • ST MCU CAN模块--TTCAN模式浅析
  • window 显示驱动开发-转换 Direct3D 固定函数状态(一)
  • 界面开发框架DevExpress XAF实践:集成.NET Aspire后如何实现自定义遥测?