当前位置:   article > 正文

Qt高级——Qt自定义标题栏

qt自定义标题栏

一、Qt自定义标题栏简介

QWidget及其子类窗体组件的标题栏受操作系统的控制,即标题栏的界面风格与操作系统的主题风格相同,工程实践中需要开发者自行定义,达到美化应用程序界面的目的。

二、Qt自定义标题栏实现

1、自定义标题栏的功能

自定义标题栏需要完成功能如下:
(1)自定义标题栏需要包含最小化按钮、最大化按钮、关闭按钮、标题标签、图标标签等图形元素。
(2)标题栏的拖拽。
(3)鼠标双击标题栏实现窗体的最大化、最小化。

2、自定义标题栏的界面布局

自定义标题栏的界面布局如下:
Qt高级——Qt自定义标题栏

3、标题栏拖拽功能的实现

窗体的拖拽平移过程如下图:
Qt高级——Qt自定义标题栏
当鼠标在窗体的标题栏按下并移动时,窗体会按照鼠标移动的轨迹进行平移。因此,窗体每次移动都是在当前位置按照鼠标移动的矢量进行移动。标题栏拖拽功能的实现需要实现mousePressEvent、mouseMoveEvent、mouseReleaseEvent三个事件处理函数。
MouseEvent中的globalPos()函数返回的是相对屏幕的位置坐标,而pos()则是返回鼠标在当前控件(即捕获该鼠标事件的控件)中的位置。
QWidget窗体的geometry().topLeft()则返回的是当前窗体的左上角在屏幕中的位置。

  1. startPos = event->globalPos();// 鼠标的全局初始位置,按下时记住 
  2. curWindowPos = geometry().topleft();// 窗体的全局位置,移动时 
  3. endPos = event->globalPos();// 鼠标按下发生移动之后的位置,移动时 
  4. move(curWindowPos+(startPos-endPos));// 根据矢量移动方向是初始位置减去末位置,移动时 
  5. startPos = endPos;// 将初始位置记为上次末位置,然后执行直到释放拖拽,移动时

实现代码如下:

  1. void TitleBar::mousePressEvent(QMouseEvent *event)
  2. {
  3. // 鼠标左键按下事件
  4. if (event->button() == Qt::LeftButton)
  5. {
  6. // 记录鼠标左键状态
  7. m_leftButtonPressed = true;
  8. //记录鼠标在屏幕中的位置
  9. m_start = event->globalPos();
  10. }
  11. }
  12. void TitleBar::mouseMoveEvent(QMouseEvent *event)
  13. {
  14. // 持续按住才做对应事件
  15. if(m_leftButtonPressed)
  16. {
  17. //将父窗体移动到父窗体原来的位置加上鼠标移动的位置:event->globalPos()-m_start
  18. parentWidget()->move(parentWidget()->geometry().topLeft() +
  19. event->globalPos() - m_start);
  20. //将鼠标在屏幕中的位置替换为新的位置
  21. m_start = event->globalPos();
  22. }
  23. }
  24. void TitleBar::mouseReleaseEvent(QMouseEvent *event)
  25. {
  26. // 鼠标左键释放
  27. if (event->button() == Qt::LeftButton)
  28. {
  29. // 记录鼠标状态
  30. m_leftButtonPressed = false;
  31. }
  32. }

4、标题栏双击实现最大化、最小化

鼠标双击事件处理函数mouseDoubleClickEvent实现如下:

  1. void TitleBar::mouseDoubleClickEvent(QMouseEvent *event)
  2. {
  3. m_maximizeButton->click();
  4. }

最大化、最小化、关闭按钮的槽函数如下:

  1. void TitleBar::onClicked()
  2. {
  3. QPushButton *pButton = qobject_cast<QPushButton *>(sender());
  4. QWidget *pWindow = this->window();
  5. if (pWindow->isTopLevel())
  6. {
  7. if (pButton == m_minimizeButton)
  8. {
  9. pWindow->showMinimized();
  10. }
  11. else if (pButton == m_maximizeButton)
  12. {
  13. pWindow->isMaximized() ? pWindow->showNormal() : pWindow->showMaximized();
  14. }
  15. else if (pButton == m_closeButton)
  16. {
  17. pWindow->close();
  18. }
  19. }
  20. }

三、Qt自定义窗体基类示例

1、自定义窗体基类的功能

自定义窗体基类的功能如下:
(1)自定义标题栏。
(2)增加内容组件,内容组件内部的界面布局完全由具体的用户决定。

2、自定义窗体基类的实现

TitleBar.h文件:

  1. #ifndef TITLEBAR_H
  2. #define TITLEBAR_H
  3. #include <QWidget>
  4. #include <QPushButton>
  5. #include <QLabel>
  6. #include <QHBoxLayout>
  7. #include <QEvent>
  8. #include <QMouseEvent>
  9. #include <QApplication>
  10. #include <QPoint>
  11. #include <QPixmap>
  12. #include <QString>
  13. /**
  14. * @brief 标题栏界面组件
  15. * @author
  16. */
  17. class TitleBar : public QWidget
  18. {
  19. Q_OBJECT
  20. public:
  21. explicit TitleBar(QWidget *parent = NULL);
  22. /**
  23. * @brief 设置标题栏标题
  24. * @param title,参数,设置的标题
  25. */
  26. void setWindowTitle(const QString& title);
  27. /**
  28. * @brief 设置标题栏的图标
  29. * @param iconPath,参数,图标的路径
  30. */
  31. void SetTitleBarIcon(const QString& iconPath);
  32. protected:
  33. /**
  34. * @brief 鼠标双击事件处理函数
  35. * @param event,参数,事件
  36. * @note 双击标题栏进行界面的最大化/还原
  37. */
  38. virtual void mouseDoubleClickEvent(QMouseEvent *event);
  39. /**
  40. * @brief 鼠标按下事件处理函数
  41. * @param event,参数,事件
  42. * @note 按下鼠标左键
  43. */
  44. virtual void mousePressEvent(QMouseEvent *event);
  45. /**
  46. * @brief 鼠标移动事件处理函数
  47. * @param event,参数,事件
  48. * @note 移动鼠标
  49. */
  50. virtual void mouseMoveEvent(QMouseEvent *event);
  51. /**
  52. * @brief 鼠标释放事件处理函数
  53. * @param event,参数,事件
  54. * @note 释放鼠标
  55. */
  56. virtual void mouseReleaseEvent(QMouseEvent *event);
  57. /**
  58. * @brief 事件过滤处理器
  59. * @param obj,参数
  60. * @param event,参数,事件
  61. * @return 成功返回true,失败返回false
  62. * @note 设置标题、图标
  63. */
  64. virtual bool eventFilter(QObject *obj, QEvent *event);
  65. /**
  66. * @brief 最大化/还原
  67. */
  68. void updateMaximize();
  69. protected slots:
  70. /**
  71. * @brief 最小化、最大化/还原、关闭按钮点击时响应的槽函数
  72. */
  73. void onClicked();
  74. private:
  75. QLabel* m_iconLabel;
  76. QLabel* m_titleLabel;
  77. QPushButton* m_minimizeButton;
  78. QPushButton* m_maximizeButton;
  79. QPushButton* m_closeButton;
  80. QPoint m_start;//起始点
  81. QPoint m_end;//结束点
  82. bool m_leftButtonPressed;//鼠标左键按下标记
  83. };
  84. #endif // TITLEBAR_H

TitleBar.cpp文件:

  1. #include "TitleBar.h"
  2. TitleBar::TitleBar(QWidget *parent) : QWidget(parent)
  3. {
  4. setFixedHeight(30);
  5. setWindowFlags(Qt::FramelessWindowHint);
  6. m_iconLabel = new QLabel(this);
  7. m_iconLabel->setFixedSize(20, 20);
  8. m_iconLabel->setScaledContents(true);
  9. m_titleLabel = new QLabel(this);
  10. m_titleLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
  11. m_minimizeButton = new QPushButton(this);
  12. m_minimizeButton->setFixedSize(27, 22);
  13. m_minimizeButton->setObjectName("minimizeButton");
  14. m_maximizeButton = new QPushButton(this);
  15. m_maximizeButton->setFixedSize(27, 22);
  16. m_maximizeButton->setObjectName("maximizeButton");
  17. m_closeButton = new QPushButton(this);
  18. m_closeButton->setFixedSize(27, 22);
  19. m_closeButton->setObjectName("closeButton");
  20. QHBoxLayout* layout = new QHBoxLayout;
  21. layout->addWidget(m_iconLabel);
  22. layout->addStretch(1);
  23. layout->addWidget(m_titleLabel);
  24. layout->addStretch(1);
  25. layout->addWidget(m_minimizeButton);
  26. layout->addWidget(m_maximizeButton);
  27. layout->addWidget(m_closeButton);
  28. setLayout(layout);
  29. setProperty("titleBar", true);
  30. setObjectName("titleBar");
  31. connect(m_minimizeButton, SIGNAL(clicked(bool)), this, SLOT(onClicked()));
  32. connect(m_maximizeButton, SIGNAL(clicked(bool)), this, SLOT(onClicked()));
  33. connect(m_closeButton, SIGNAL(clicked(bool)), this, SLOT(onClicked()));
  34. }
  35. void TitleBar::setWindowTitle(const QString &title)
  36. {
  37. m_titleLabel->setAlignment(Qt::AlignCenter);
  38. m_titleLabel->setText(title);
  39. }
  40. void TitleBar::SetTitleBarIcon(const QString &iconPath)
  41. {
  42. QPixmap map(iconPath);
  43. m_iconLabel->setPixmap(map);
  44. }
  45. void TitleBar::mouseDoubleClickEvent(QMouseEvent *event)
  46. {
  47. m_maximizeButton->click();
  48. }
  49. void TitleBar::mousePressEvent(QMouseEvent *event)
  50. {
  51. // 鼠标左键按下事件
  52. if (event->button() == Qt::LeftButton)
  53. {
  54. // 记录鼠标左键状态
  55. m_leftButtonPressed = true;
  56. //记录鼠标在屏幕中的位置
  57. m_start = event->globalPos();
  58. }
  59. }
  60. void TitleBar::mouseMoveEvent(QMouseEvent *event)
  61. {
  62. // 持续按住才做对应事件
  63. if(m_leftButtonPressed)
  64. {
  65. //将父窗体移动到父窗体原来的位置加上鼠标移动的位置:event->globalPos()-m_start
  66. parentWidget()->move(parentWidget()->geometry().topLeft() +
  67. event->globalPos() - m_start);
  68. //将鼠标在屏幕中的位置替换为新的位置
  69. m_start = event->globalPos();
  70. }
  71. }
  72. void TitleBar::mouseReleaseEvent(QMouseEvent *event)
  73. {
  74. // 鼠标左键释放
  75. if (event->button() == Qt::LeftButton)
  76. {
  77. // 记录鼠标状态
  78. m_leftButtonPressed = false;
  79. }
  80. }
  81. bool TitleBar::eventFilter(QObject *obj, QEvent *event)
  82. {
  83. switch(event->type())
  84. {
  85. //设置标题
  86. case QEvent::WindowTitleChange:
  87. {
  88. QWidget *pWidget = qobject_cast<QWidget *>(obj);
  89. if (pWidget)
  90. {
  91. m_titleLabel->setText(pWidget->windowTitle());
  92. return true;
  93. }
  94. }
  95. //设置图标
  96. case QEvent::WindowIconChange:
  97. {
  98. QWidget *pWidget = qobject_cast<QWidget *>(obj);
  99. if (pWidget)
  100. {
  101. QIcon icon = pWidget->windowIcon();
  102. m_iconLabel->setPixmap(icon.pixmap(m_iconLabel->size()));
  103. return true;
  104. }
  105. }
  106. // 窗口状态变化、窗口大小变化
  107. case QEvent::WindowStateChange:
  108. case QEvent::Resize:
  109. updateMaximize();
  110. return true;
  111. }
  112. return QWidget::eventFilter(obj, event);
  113. }
  114. void TitleBar::updateMaximize()
  115. {
  116. QWidget *pWindow = this->window();
  117. if (pWindow->isTopLevel())
  118. {
  119. bool bMaximize = pWindow->isMaximized();
  120. if (bMaximize)
  121. {
  122. m_maximizeButton->setToolTip(tr("Restore"));
  123. m_maximizeButton->setProperty("maximizeProperty", "restore");
  124. }
  125. else
  126. {
  127. m_maximizeButton->setProperty("maximizeProperty", "maximize");
  128. m_maximizeButton->setToolTip(tr("Maximize"));
  129. }
  130. m_maximizeButton->setStyle(QApplication::style());
  131. }
  132. }
  133. void TitleBar::onClicked()
  134. {
  135. QPushButton *pButton = qobject_cast<QPushButton *>(sender());
  136. QWidget *pWindow = this->window();
  137. if (pWindow->isTopLevel())
  138. {
  139. if (pButton == m_minimizeButton)
  140. {
  141. pWindow->showMinimized();
  142. }
  143. else if (pButton == m_maximizeButton)
  144. {
  145. pWindow->isMaximized() ? pWindow->showNormal() : pWindow->showMaximized();
  146. }
  147. else if (pButton == m_closeButton)
  148. {
  149. pWindow->close();
  150. }
  151. }
  152. }

QWindowBase.h文件:

  1. #ifndef QWINDOWBASE_H
  2. #define QWINDOWBASE_H
  3. #include <QFrame>
  4. #include <QWidget>
  5. #include <QVBoxLayout>
  6. #include "TitleBar.h"
  7. /**
  8. * @brief 界面组件基类
  9. * @note QWindowBase界面组件主要用作顶层窗口,对于非顶层窗口的界面组件使用QWidget。
  10. */
  11. class QWindowBase : public QFrame
  12. {
  13. Q_OBJECT
  14. public:
  15. QWindowBase(QFrame* parent = NULL);
  16. /**
  17. * @brief 设置标题
  18. * @param title,输入参数,标题内容
  19. */
  20. void setWindowTitle(const QString& title);
  21. /**
  22. * @brief 设置标题栏的图标
  23. * @param iconPath,输入参数,图标资源路径
  24. */
  25. void SetTitleBarIcon(const QString& iconPath);
  26. /**
  27. * @brief 获取内容组件对象指针
  28. * @return 返回QWidget*
  29. */
  30. QWidget* contentWidget();
  31. /**
  32. * @brief 设置标题栏高度
  33. * @param h,输入参数,标题栏高度
  34. */
  35. void setWindowTitleHeight(int h);
  36. private:
  37. QWidget* m_contentWidget;//内容组件
  38. TitleBar* m_titleBar;//标题栏
  39. QVBoxLayout* m_layout;//布局管理器
  40. };
  41. #endif // QWINDOWBASE_H

QWindowBase.cpp文件:

  1. #include "QWindowBase.h"
  2. QWindowBase::QWindowBase(QFrame *parent): QFrame(parent)
  3. {
  4. setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
  5. m_titleBar = new TitleBar(this);
  6. m_contentWidget = new QWidget(this);
  7. m_contentWidget->setObjectName("Contents");
  8. m_layout = new QVBoxLayout;
  9. m_layout->addWidget(m_titleBar);
  10. m_layout->addWidget(m_contentWidget);
  11. m_layout->setSpacing(0);
  12. m_layout->setContentsMargins(0, 0, 0, 0);
  13. setLayout(m_layout);
  14. }
  15. void QWindowBase::setWindowTitle(const QString &title)
  16. {
  17. m_titleBar->setWindowTitle(title);
  18. }
  19. void QWindowBase::SetTitleBarIcon(const QString &iconPath)
  20. {
  21. m_titleBar->SetTitleBarIcon(iconPath);
  22. }
  23. QWidget *QWindowBase::contentWidget()
  24. {
  25. return m_contentWidget;
  26. }
  27. void QWindowBase::setWindowTitleHeight(int h)
  28. {
  29. m_titleBar->setFixedHeight(h);
  30. }

CommonHelper.h文件:

  1. #ifndef COMMONHELPER_H
  2. #define COMMONHELPER_H
  3. #include <QString>
  4. #include <QFile>
  5. #include <QApplication>
  6. #include <QDebug>
  7. #include <QColor>
  8. #include <QPalette>
  9. /**
  10. * @brief 通用功能辅助类
  11. */
  12. class CommonHelper
  13. {
  14. public:
  15. /**
  16. * @brief 为应用程序设置QSS样式表
  17. * @param filepath,输入参数,QSS文件路径
  18. */
  19. static void setStyleSheet(const QString& filepath)
  20. {
  21. //加载样式文件
  22. QFile qss(filepath);
  23. if(qss.open(QFile::ReadOnly))
  24. {
  25. QString stylesheet = QLatin1String(qss.readAll());
  26. QString paletteColor = stylesheet.mid(20, 7);
  27. qApp->setPalette(QPalette(QColor(paletteColor)));
  28. qApp->setStyleSheet(stylesheet);
  29. }
  30. }
  31. };
  32. #endif // COMMONHELPER_H

main.cpp文件:

  1. #include <QApplication>
  2. #include "CommonHelper.h"
  3. #include "QWindowBase.h"
  4. #include <QPushButton>
  5. #include <QVBoxLayout>
  6. #include <QHBoxLayout>
  7. #include <QTreeView>
  8. int main(int argc, char *argv[])
  9. {
  10. QApplication a(argc, argv);
  11. QWindowBase w;
  12. w.setWindowTitle("WidgetBase");
  13. QPushButton* button1 = new QPushButton("OK");
  14. QHBoxLayout* hLayout1 = new QHBoxLayout;
  15. hLayout1->addStretch(1);
  16. hLayout1->addWidget(button1);
  17. QVBoxLayout* layout = new QVBoxLayout;
  18. QTreeView* treeView = new QTreeView;
  19. layout->addWidget(treeView);
  20. layout->addLayout(hLayout1);
  21. layout->addStretch(1);
  22. w.contentWidget()->setLayout(layout);
  23. w.setWindowTitleHeight(40);
  24. w.show();
  25. CommonHelper::setStyleSheet("://qss/lightblue.qss");
  26. return a.exec();
  27. }

工程文件:

  1. QT += core gui
  2. greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
  3. TARGET = TitleBarDemo
  4. TEMPLATE = app
  5. # The following define makes your compiler emit warnings if you use
  6. # any feature of Qt which has been marked as deprecated (the exact warnings
  7. # depend on your compiler). Please consult the documentation of the
  8. # deprecated API in order to know how to port your code away from it.
  9. DEFINES += QT_DEPRECATED_WARNINGS
  10. # You can also make your code fail to compile if you use deprecated APIs.
  11. # In order to do so, uncomment the following line.
  12. # You can also select to disable deprecated APIs only up to a certain version of Qt.
  13. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
  14. SOURCES += \
  15. main.cpp \
  16. TitleBar.cpp \
  17. QWindowBase.cpp
  18. HEADERS += \
  19. TitleBar.h \
  20. CommonHelper.h \
  21. QWindowBase.h
  22. RESOURCES += \
  23. TitileBarDemo.qrc

工程目录结构:
Qt高级——Qt自定义标题栏

3、自定义窗体基类结果展示

运行结果:
Qt高级——Qt自定义标题栏

源码:http://down.51cto.com/data/2457159

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/234976
推荐阅读
相关标签
  

闽ICP备14008679号