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

打印 上一主题 下一主题

主题 2057|帖子 2057|积分 6171

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

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

1. 设置无边框窗口

首先,在 MainWindow 的构造函数中移除默认边框:
  1. MainWindow::MainWindow(QWidget *parent)
  2.     : QMainWindow(parent)
  3. {
  4.     ui->setupUi(this);
  5.    
  6.     // 设置无边框窗口
  7.     setWindowFlags(Qt::FramelessWindowHint);
  8.    
  9.     // 连接按钮信号(最小化、最大化/还原、关闭)
  10.     connect(ui->toolButton_minimize, &QToolButton::clicked, this, &MainWindow::showMinimized);
  11.     connect(ui->toolButton_maximize, &QToolButton::clicked, this, [this]() {
  12.         if (this->isMaximized()) {
  13.             this->showNormal();  // 如果已最大化,则还原
  14.         } else {
  15.             this->showMaximized();  // 否则最大化
  16.         }
  17.     });
  18.     connect(ui->toolButton_close, &QToolButton::clicked, this, &MainWindow::close);
  19. }
复制代码
这里:


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

2. 实现窗口拖动功能

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

  • 在 MainWindow 类中添加成员变量和重写鼠标变乱
  1. // MainWindow.h
  2. protected:
  3.     void mousePressEvent(QMouseEvent *event) override;
  4.     void mouseMoveEvent(QMouseEvent *event) override;
  5. private:
  6.     QPoint m_dragPosition;  // 记录鼠标按下时的位置
复制代码

  • 实现鼠标变乱
  1. // MainWindow.cpp
  2. void MainWindow::mousePressEvent(QMouseEvent *event)
  3. {
  4.     if (event->button() == Qt::LeftButton) {
  5.         m_dragPosition = event->globalPos() - frameGeometry().topLeft();
  6.         event->accept();
  7.     }
  8.     QMainWindow::mousePressEvent(event);
  9. }
  10. void MainWindow::mouseMoveEvent(QMouseEvent *event)
  11. {
  12.     if (event->buttons() & Qt::LeftButton) {
  13.         move(event->globalPos() - m_dragPosition);  // 移动窗口
  14.         event->accept();
  15.     }
  16.     QMainWindow::mouseMoveEvent(event);
  17. }
复制代码


  • mousePressEvent:当鼠标左键按下时,记载当前鼠标位置相对于窗口左上角的偏移量。
  • mouseMoveEvent:当鼠标左键按下并移动时,盘算窗口新位置并移动窗口。

3. 完整代码示例

MainWindow.h

  1. #include <QMainWindow>
  2. #include <QMouseEvent>
  3. namespace Ui {
  4. class MainWindow;
  5. }
  6. class MainWindow : public QMainWindow
  7. {
  8.     Q_OBJECT
  9. public:
  10.     explicit MainWindow(QWidget *parent = nullptr);
  11.     ~MainWindow();
  12. protected:
  13.     void mousePressEvent(QMouseEvent *event) override;
  14.     void mouseMoveEvent(QMouseEvent *event) override;
  15. private:
  16.     Ui::MainWindow *ui;
  17.     QPoint m_dragPosition;
  18. };
复制代码
MainWindow.cpp

  1. #include "MainWindow.h"
  2. #include "ui_MainWindow.h"
  3. MainWindow::MainWindow(QWidget *parent)
  4.     : QMainWindow(parent)
  5.     , ui(new Ui::MainWindow)
  6. {
  7.     ui->setupUi(this);
  8.    
  9.     // 设置无边框窗口
  10.     setWindowFlags(Qt::FramelessWindowHint);
  11.    
  12.     // 连接按钮信号
  13.     connect(ui->toolButton_minimize, &QToolButton::clicked, this, &MainWindow::showMinimized);
  14.     connect(ui->toolButton_maximize, &QToolButton::clicked, this, [this]() {
  15.         if (this->isMaximized()) {
  16.             this->showNormal();  // 还原
  17.         } else {
  18.             this->showMaximized();  // 最大化
  19.         }
  20.     });
  21.     connect(ui->toolButton_close, &QToolButton::clicked, this, &MainWindow::close);
  22. }
  23. MainWindow::~MainWindow()
  24. {
  25.     delete ui;
  26. }
  27. void MainWindow::mousePressEvent(QMouseEvent *event)
  28. {
  29.     if (event->button() == Qt::LeftButton) {
  30.         m_dragPosition = event->globalPos() - frameGeometry().topLeft();
  31.         event->accept();
  32.     }
  33.     QMainWindow::mousePressEvent(event);
  34. }
  35. void MainWindow::mouseMoveEvent(QMouseEvent *event)
  36. {
  37.     if (event->buttons() & Qt::LeftButton) {
  38.         move(event->globalPos() - m_dragPosition);
  39.         event->accept();
  40.     }
  41.     QMainWindow::mouseMoveEvent(event);
  42. }
复制代码

4. 效果



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

5. 进阶优化


  • 限制拖动区域
    如果只想让窗口的某个区域(如标题栏)可拖动,可以修改 mousePressEvent:
    1. if (event->button() == Qt::LeftButton && ui->titleBarWidget->geometry().contains(event->pos())) {
    2.     m_dragPosition = event->globalPos() - frameGeometry().topLeft();
    3.     event->accept();
    4. }
    复制代码
  • 双击最大化/还原
    可以重写 mouseDoubleClickEvent 实现双击标题栏最大化/还原。
  • 窗口阴影效果
    利用 QGraphicsDropShadowEffect 让无边框窗口看起来更雅观。

6. 总结

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

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

一给

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表