当前位置:   article > 正文

Qt之自定义界面(添加自定义标题栏)

qt 小标题设计

简述

通过上节内容,我们实现了自定义窗体的移动,但是我们缺少一个标题栏来显示窗体的图标、标题,以及控制窗体最小化、最大化、关闭的按钮。

自定义标题栏后,所有的控件我们都可以定制,比如:在标题栏中添加换肤、设置按钮以及其他控件。

效果

这里写图片描述

自定义标题栏

实现

title_bar.h

  1. #ifndef TITLE_BAR
  2. #define TITLE_BAR
  3. #include <QWidget>
  4. class QLabel;
  5. class QPushButton;
  6. class TitleBar : public QWidget
  7. {
  8. Q_OBJECT
  9. public:
  10. explicit TitleBar(QWidget *parent = 0);
  11. ~TitleBar();
  12. protected:
  13. // 双击标题栏进行界面的最大化/还原
  14. virtual void mouseDoubleClickEvent(QMouseEvent *event);
  15. // 进行鼠界面的拖动
  16. virtual void mousePressEvent(QMouseEvent *event);
  17. // 设置界面标题与图标
  18. virtual bool eventFilter(QObject *obj, QEvent *event);
  19. private slots:
  20. // 进行最小化、最大化/还原、关闭操作
  21. void onClicked();
  22. private:
  23. // 最大化/还原
  24. void updateMaximize();
  25. private:
  26. QLabel *m_pIconLabel;
  27. QLabel *m_pTitleLabel;
  28. QPushButton *m_pMinimizeButton;
  29. QPushButton *m_pMaximizeButton;
  30. QPushButton *m_pCloseButton;
  31. };
  32. #endif // TITLE_BAR
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

title_bar.cpp

  1. #include <QLabel>
  2. #include <QPushButton>
  3. #include <QHBoxLayout>
  4. #include <QEvent>
  5. #include <QMouseEvent>
  6. #include <QApplication>
  7. #include "title_bar.h"
  8. #ifdef Q_OS_WIN
  9. #pragma comment(lib, "user32.lib")
  10. #include <qt_windows.h>
  11. #endif
  12. TitleBar::TitleBar(QWidget *parent)
  13. : QWidget(parent)
  14. {
  15. setFixedHeight(30);
  16. m_pIconLabel = new QLabel(this);
  17. m_pTitleLabel = new QLabel(this);
  18. m_pMinimizeButton = new QPushButton(this);
  19. m_pMaximizeButton = new QPushButton(this);
  20. m_pCloseButton = new QPushButton(this);
  21. m_pIconLabel->setFixedSize(20, 20);
  22. m_pIconLabel->setScaledContents(true);
  23. m_pTitleLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
  24. m_pMinimizeButton->setFixedSize(27, 22);
  25. m_pMaximizeButton->setFixedSize(27, 22);
  26. m_pCloseButton->setFixedSize(27, 22);
  27. m_pTitleLabel->setObjectName("whiteLabel");
  28. m_pMinimizeButton->setObjectName("minimizeButton");
  29. m_pMaximizeButton->setObjectName("maximizeButton");
  30. m_pCloseButton->setObjectName("closeButton");
  31. m_pMinimizeButton->setToolTip("Minimize");
  32. m_pMaximizeButton->setToolTip("Maximize");
  33. m_pCloseButton->setToolTip("Close");
  34. QHBoxLayout *pLayout = new QHBoxLayout(this);
  35. pLayout->addWidget(m_pIconLabel);
  36. pLayout->addSpacing(5);
  37. pLayout->addWidget(m_pTitleLabel);
  38. pLayout->addWidget(m_pMinimizeButton);
  39. pLayout->addWidget(m_pMaximizeButton);
  40. pLayout->addWidget(m_pCloseButton);
  41. pLayout->setSpacing(0);
  42. pLayout->setContentsMargins(5, 0, 5, 0);
  43. setLayout(pLayout);
  44. connect(m_pMinimizeButton, SIGNAL(clicked(bool)), this, SLOT(onClicked()));
  45. connect(m_pMaximizeButton, SIGNAL(clicked(bool)), this, SLOT(onClicked()));
  46. connect(m_pCloseButton, SIGNAL(clicked(bool)), this, SLOT(onClicked()));
  47. }
  48. TitleBar::~TitleBar()
  49. {
  50. }
  51. void TitleBar::mouseDoubleClickEvent(QMouseEvent *event)
  52. {
  53. Q_UNUSED(event);
  54. emit m_pMaximizeButton->clicked();
  55. }
  56. void TitleBar::mousePressEvent(QMouseEvent *event)
  57. {
  58. #ifdef Q_OS_WIN
  59. if (ReleaseCapture())
  60. {
  61. QWidget *pWindow = this->window();
  62. if (pWindow->isTopLevel())
  63. {
  64. SendMessage(HWND(pWindow->winId()), WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);
  65. }
  66. }
  67. event->ignore();
  68. #else
  69. #endif
  70. }
  71. bool TitleBar::eventFilter(QObject *obj, QEvent *event)
  72. {
  73. switch (event->type())
  74. {
  75. case QEvent::WindowTitleChange:
  76. {
  77. QWidget *pWidget = qobject_cast<QWidget *>(obj);
  78. if (pWidget)
  79. {
  80. m_pTitleLabel->setText(pWidget->windowTitle());
  81. return true;
  82. }
  83. }
  84. case QEvent::WindowIconChange:
  85. {
  86. QWidget *pWidget = qobject_cast<QWidget *>(obj);
  87. if (pWidget)
  88. {
  89. QIcon icon = pWidget->windowIcon();
  90. m_pIconLabel->setPixmap(icon.pixmap(m_pIconLabel->size()));
  91. return true;
  92. }
  93. }
  94. case QEvent::WindowStateChange:
  95. case QEvent::Resize:
  96. updateMaximize();
  97. return true;
  98. }
  99. return QWidget::eventFilter(obj, event);
  100. }
  101. void TitleBar::onClicked()
  102. {
  103. QPushButton *pButton = qobject_cast<QPushButton *>(sender());
  104. QWidget *pWindow = this->window();
  105. if (pWindow->isTopLevel())
  106. {
  107. if (pButton == m_pMinimizeButton)
  108. {
  109. pWindow->showMinimized();
  110. }
  111. else if (pButton == m_pMaximizeButton)
  112. {
  113. pWindow->isMaximized() ? pWindow->showNormal() : pWindow->showMaximized();
  114. }
  115. else if (pButton == m_pCloseButton)
  116. {
  117. pWindow->close();
  118. }
  119. }
  120. }
  121. void TitleBar::updateMaximize()
  122. {
  123. QWidget *pWindow = this->window();
  124. if (pWindow->isTopLevel())
  125. {
  126. bool bMaximize = pWindow->isMaximized();
  127. if (bMaximize)
  128. {
  129. m_pMaximizeButton->setToolTip(tr("Restore"));
  130. m_pMaximizeButton->setProperty("maximizeProperty", "restore");
  131. }
  132. else
  133. {
  134. m_pMaximizeButton->setProperty("maximizeProperty", "maximize");
  135. m_pMaximizeButton->setToolTip(tr("Maximize"));
  136. }
  137. m_pMaximizeButton->setStyle(QApplication::style());
  138. }
  139. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160

接口说明

  • mousePressEvent

之前,我们将界面移动的事件写在主界面里面,这会有一个问题,一般情况下,是界面随着标题栏的移动而移动,而并非界面中的所有位置都可以进行拖动,所以我们将事件写在标题栏中比较合理。

  • mouseDoubleClickEvent

双击标题栏会进行窗体的最大化/还原,所以我们需要重写此事件进行控制。

  • eventFilter

    1. 事件过滤器,这里被监听的窗体为标题栏所在的窗体,所以当窗体标题、图标等信息发生改变时,标题栏也应该随之改变。

    2. 最好不要通过直接调用接口的形式来操作对应的行为,比如:TitleBar中定义一个public函数来专门修改标题与图标,这样会造成不必要的麻烦,因为Qt本身就是基于事件的,所以此处采用过滤器的方式。

  • updateMaximize

因为窗体大小发生变化的时候,最大化的图标、提示应该对应的发生变化,所以在eventFilter中事件触发时调用。

使用方式

  1. Widget::Widget(QWidget *parent)
  2. : QWidget(parent)
  3. {
  4. setWindowFlags(Qt::FramelessWindowHint | windowFlags());
  5. TitleBar *pTitleBar = new TitleBar(this);
  6. installEventFilter(pTitleBar);
  7. resize(400, 300);
  8. setWindowTitle("Custom Window");
  9. setWindowIcon(QIcon(":/Images/logo"));
  10. QPalette pal(palette());
  11. pal.setColor(QPalette::Background, QColor(50, 50, 50));
  12. setAutoFillBackground(true);
  13. setPalette(pal);
  14. QVBoxLayout *pLayout = new QVBoxLayout();
  15. pLayout->addWidget(pTitleBar);
  16. pLayout->addStretch();
  17. pLayout->setSpacing(0);
  18. pLayout->setContentsMargins(0, 0, 0, 0);
  19. setLayout(pLayout);
  20. }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

注意

installEventFilter必须在setWindowTitle、setWindowIcon之前调用,因为必须先安装事件过滤器,相应事件触发时,才会进入标题栏的eventFilter事件中。

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号