当前位置:   article > 正文

QT快速开发自定义标题栏_qt如何把标题栏重新绘制

qt如何把标题栏重新绘制

前言

大家在用QT进行客户端开发的时候,难免都会觉得原生的QT窗口标题栏很丑,希望能自绘漂亮的标题栏,实现方法其实也比较简单,网上资料也挺多,方法基本都差不多,不过我觉得不够简洁,对此我特地封装总结了一个最高效快捷的方法,3分钟实现一个自绘制标题栏,包含:左上角图标、标题、按钮、双击标题栏、最大化时候拖拽缩小、菜单栏等功能。

效果

方法

1、目标窗口添加标题栏、最大化最小化关闭按钮(该步最好每次使用时,从模板程序中直接复制)

2、窗口基类从QDialog改为QFramelessDialog,如果是QWidget的话,请参考QFramelessDialog自行编写QFramelessWidget即可,非常简单,只需要将QDialog改成QWidget即可,至于为什么我写程序更喜欢用QDialog而不是QWidget,主要原因是QDialog默认自带外边框,设置外边框更简单,而QWidget设置外边框比较麻烦,必须在ui中将边框宽度pad预留出来。

3、窗口构造函数中,调用无边框窗体初始化函数,头文件中已经写好几个宏函数直接调用即可,使用宏的情况下,必须保证标题栏、按钮对象名称一致,注意调用初始化函数一定要在ui.setupUi(this);后面。

核心初始化函数

  1. void Init(QWidget *widget_title, //标题栏对象
  2. QPushButton *menuButton_Close,//关闭按钮
  3. QPushButton *menuButton_Max, //最大化按钮
  4. QPushButton *menuButton_Min, //最小化按钮
  5. bool bResize, //窗体支持resize
  6. bool bMinHide, //点击close按钮时隐藏窗口,通常用在主窗口中
  7. bool bConnectClose); //当bMinHide为true时,是否自动处理隐藏

宏解释:

FRAMELESS_DIALOG_INIT    模态对话框(只有关闭按钮)

FRAMELESS_MAIN_DIALOG_INIT   常用主窗口(包含最大化 、最小化、关闭按钮、可resize)

关于Demo中qss样式、编辑可参考作者早期博文《QT-智能QSS设计器》

https://blog.csdn.net/redchairman/article/details/82012984

代码

  1. #ifndef QFRAMELESSDIALOG_H
  2. #define QFRAMELESSDIALOG_H
  3. #include <QDialog>
  4. class QFramelessDialog : public QDialog
  5. {
  6. Q_OBJECT
  7. public:
  8. QFramelessDialog(QWidget *parent);
  9. ~QFramelessDialog();
  10. void Init(QWidget *widget_title,
  11. QPushButton *menuButton_Close,
  12. QPushButton *menuButton_Max,
  13. QPushButton *menuButton_Min,
  14. bool bResize,
  15. bool bMinClose,
  16. bool bConnectClose);
  17. void setResizeable(bool resizeable);
  18. virtual void CloseDialog();
  19. private:
  20. bool m_bMaximized;
  21. bool m_bMoveable;
  22. QPoint dragPosition;
  23. QRect m_rcNormal;
  24. protected:
  25. void mouseMoveEvent(QMouseEvent *e);
  26. void mousePressEvent(QMouseEvent *e);
  27. void mouseReleaseEvent(QMouseEvent *);
  28. void mouseDoubleClickEvent(QMouseEvent *event);
  29. bool nativeEvent(const QByteArray & eventType, void * message, long * result);
  30. void paintEvent(QPaintEvent *event);
  31. void keyPressEvent(QKeyEvent* e);
  32. public slots:
  33. /* void sltCloseClick();*/
  34. void sltClickMin();
  35. void sltClickMaxRestore();
  36. void sltCloseDialog();
  37. public:
  38. bool m_bResize;
  39. QPushButton *m_menuButton_Close;
  40. QPushButton *m_menuButton_Max;
  41. QPushButton *m_menuButton_Min;
  42. QWidget *m_widget_title;
  43. bool m_bMinClose;
  44. bool m_bConnectClose;
  45. };
  46. #define FRAMELESS_DIALOG_INIT() Init(ui.widget_title, ui.menuButton_Close, nullptr, nullptr, false, false, true)
  47. #define FRAMELESS_MAIN_DIALOG_INIT() Init(ui.widget_title, ui.menuButton_Close, ui.menuButton_Max, ui.menuButton_Min, true, true, true)
  48. #define FRAMELESS_MAIN_DIALOG_NOCLOSE_INIT() Init(ui.widget_title, ui.menuButton_Close, ui.menuButton_Max, ui.menuButton_Min, true, true, false)
  49. #define FRAMELESS_DIALOG_INIT2() Init(ui->widget_title, ui->menuButton_Close, nullptr, nullptr, false, false, true)
  50. #define FRAMELESS_MAIN_DIALOG_INIT2() Init(ui->widget_title, ui->menuButton_Close, ui->menuButton_Max, ui->menuButton_Min, true, true, true)
  51. #define FRAMELESS_MAIN_DIALOG_NOCLOSE_INIT2() Init(ui->widget_title, ui->menuButton_Close, ui->menuButton_Max, ui->menuButton_Min, true, true, false)
  52. #endif // QFRAMELESSDIALOG_H

 

  1. #include "stdafx.h"
  2. #include "QFramelessDialog.h"
  3. #include "QIconHelper.hpp"
  4. QFramelessDialog::QFramelessDialog(QWidget *parent)
  5. : QDialog(parent)
  6. , m_bMaximized(false)
  7. , m_bMoveable(false)
  8. , m_bResize(false)
  9. , m_menuButton_Close(nullptr)
  10. , m_menuButton_Max(nullptr)
  11. , m_menuButton_Min(nullptr)
  12. , m_widget_title(nullptr)
  13. , m_bMinClose(false)
  14. {
  15. /* setAttribute(Qt::WA_TranslucentBackground);*/
  16. setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog | Qt::WindowMinMaxButtonsHint);
  17. setWindowModality(Qt::WindowModal);
  18. setFocusPolicy(Qt::ClickFocus);
  19. }
  20. QFramelessDialog::~QFramelessDialog()
  21. {
  22. }
  23. void QFramelessDialog::Init(QWidget *widget_title,
  24. QPushButton *menuButton_Close,
  25. QPushButton *menuButton_Max,
  26. QPushButton *menuButton_Min,
  27. bool bResize,
  28. bool bMinClose,
  29. bool bConnectClose)
  30. {
  31. m_bResize = bResize;
  32. m_bMinClose = bMinClose;
  33. m_bConnectClose = bConnectClose;
  34. m_menuButton_Min = menuButton_Min;
  35. m_menuButton_Max = menuButton_Max;
  36. m_menuButton_Close = menuButton_Close;
  37. m_widget_title = widget_title;
  38. if (m_menuButton_Close)
  39. {
  40. m_menuButton_Close->setFocusPolicy(Qt::ClickFocus);
  41. QIconHelper::SetIcon(m_menuButton_Close, QChar(0xf00d), 12);
  42. if (m_bMinClose)
  43. {
  44. if (m_bConnectClose)
  45. {
  46. connect(m_menuButton_Close, SIGNAL(clicked()), this, SLOT(hide()));
  47. }
  48. }
  49. else
  50. {
  51. connect(m_menuButton_Close, SIGNAL(clicked()), this, SLOT(sltCloseDialog()));
  52. }
  53. }
  54. if (m_menuButton_Max)
  55. {
  56. m_menuButton_Max->setFocusPolicy(Qt::ClickFocus);
  57. QIconHelper::SetIcon(m_menuButton_Max, QChar(0xf096), 12);
  58. connect(m_menuButton_Max, SIGNAL(clicked()), this, SLOT(sltClickMaxRestore()));
  59. }
  60. if (m_menuButton_Min)
  61. {
  62. m_menuButton_Min->setFocusPolicy(Qt::ClickFocus);
  63. QIconHelper::SetIcon(m_menuButton_Min, QChar(0xf068), 12);
  64. connect(m_menuButton_Min, SIGNAL(clicked()), this, SLOT(sltClickMin()));
  65. }
  66. return;
  67. }
  68. void QFramelessDialog::CloseDialog()
  69. {
  70. close();
  71. }
  72. void QFramelessDialog::sltCloseDialog()
  73. {
  74. CloseDialog();
  75. }
  76. void QFramelessDialog::mousePressEvent(QMouseEvent *event)
  77. {
  78. if (isFullScreen())
  79. {
  80. return;
  81. }
  82. if (event->button() == Qt::LeftButton && m_widget_title)
  83. {
  84. dragPosition = event->globalPos() - frameGeometry().topLeft();
  85. QRect rect = m_widget_title->rect();
  86. if (rect.contains(event->pos()))
  87. {
  88. m_bMoveable = true;
  89. }
  90. }
  91. event->accept();
  92. }
  93. void QFramelessDialog::mouseMoveEvent(QMouseEvent *event)
  94. {
  95. if (isFullScreen())
  96. {
  97. return;
  98. }
  99. if (event->buttons() & Qt::LeftButton && m_bMoveable)
  100. {
  101. if (isMaximized())
  102. {
  103. int nWidth = m_rcNormal.width();
  104. int nHeight = m_rcNormal.height();
  105. float fx = (float)event->pos().x() / (float)rect().width();
  106. //屏幕大小
  107. int old_x = m_rcNormal.width() * fx + m_rcNormal.left();
  108. int old_y = m_rcNormal.top() + event->pos().y();
  109. QPoint pt_new(m_rcNormal.left() + event->globalPos().x() - old_x, m_rcNormal.top() + event->globalPos().y() - old_y);
  110. m_rcNormal.moveTopLeft(pt_new);
  111. sltClickMaxRestore();
  112. //m_rcNormal
  113. dragPosition = event->globalPos() - frameGeometry().topLeft();
  114. }
  115. else
  116. {
  117. move(event->globalPos() - dragPosition);
  118. }
  119. }
  120. event->accept();
  121. }
  122. void QFramelessDialog::mouseReleaseEvent(QMouseEvent *event)
  123. {
  124. if (isFullScreen())
  125. {
  126. return;
  127. }
  128. if (m_bMoveable)
  129. {
  130. m_bMoveable = false;
  131. }
  132. event->accept();
  133. }
  134. void QFramelessDialog::mouseDoubleClickEvent(QMouseEvent *event)
  135. {
  136. if (m_bResize == false)
  137. {
  138. return;
  139. }
  140. if (m_menuButton_Max == nullptr || m_menuButton_Min == nullptr)
  141. {
  142. return;
  143. }
  144. if (isFullScreen())
  145. {
  146. return;
  147. }
  148. if (event->buttons() & Qt::LeftButton && m_widget_title)
  149. {
  150. QRect rect = m_widget_title->rect();
  151. if (rect.contains(event->pos()))
  152. {
  153. sltClickMaxRestore();
  154. }
  155. }
  156. event->accept();
  157. }
  158. void QFramelessDialog::sltClickMin()
  159. {
  160. showMinimized();
  161. }
  162. void QFramelessDialog::sltClickMaxRestore()
  163. {
  164. if (isMaximized())
  165. {
  166. showNormal();
  167. setGeometry(m_rcNormal);
  168. qDebug() << m_rcNormal;
  169. QIconHelper::SetIcon(m_menuButton_Max, QChar(0xf096), 10);
  170. m_menuButton_Max->setToolTip(QStringLiteral("最大化"));
  171. }
  172. else
  173. {
  174. m_rcNormal = geometry();
  175. showMaximized();
  176. QIconHelper::SetIcon(m_menuButton_Max, QChar(0xf079), 10);
  177. m_menuButton_Max->setToolTip(QStringLiteral("还原"));
  178. }
  179. }
  180. bool QFramelessDialog::nativeEvent(const QByteArray & eventType, void * message, long * result)
  181. {
  182. Q_UNUSED(eventType);
  183. const int HIT_BORDER = 4;
  184. const MSG *msg = static_cast<MSG*>(message);
  185. if (msg->message == WM_NCCALCSIZE)
  186. {
  187. *result = 0;
  188. return true;
  189. }
  190. else if (msg->message == WM_NCHITTEST)
  191. {
  192. if (m_bResize == false || m_widget_title == nullptr)
  193. {
  194. return QDialog::nativeEvent(eventType, message, result);
  195. }
  196. if (isMaximized())
  197. {
  198. return false;
  199. }
  200. int xPos = ((int)(short)LOWORD(msg->lParam)) - this->frameGeometry().x();
  201. int yPos = ((int)(short)HIWORD(msg->lParam)) - this->frameGeometry().y();
  202. if (xPos >= 0 && xPos < HIT_BORDER && yPos >= 0 && yPos < HIT_BORDER) {
  203. *result = HTTOPLEFT;
  204. return true;
  205. }
  206. if (xPos >(this->width() - HIT_BORDER) && xPos < (this->width() - 0) && yPos > 0 && yPos < HIT_BORDER) {
  207. *result = HTTOPRIGHT;
  208. return true;
  209. }
  210. if (xPos > 0 && xPos < HIT_BORDER && yPos >(this->height() - HIT_BORDER) && yPos < (this->height() - 0)) {
  211. *result = HTBOTTOMLEFT;
  212. return true;
  213. }
  214. if (xPos >(this->width() - HIT_BORDER) && xPos < (this->width() - 0) && yPos >(this->height() - HIT_BORDER) && yPos < (this->height() - 0)) {
  215. *result = HTBOTTOMRIGHT;
  216. return true;
  217. }
  218. if (xPos >= 0 && xPos < HIT_BORDER) {
  219. *result = HTLEFT;
  220. return true;
  221. }
  222. if (xPos >(this->width() - HIT_BORDER) && xPos < (this->width() - 0)) {
  223. *result = HTRIGHT;
  224. return true;
  225. }
  226. if (yPos >= 0 && yPos < HIT_BORDER) {
  227. *result = HTTOP;
  228. return true;
  229. }
  230. if (yPos >(this->height() - HIT_BORDER) && yPos < (this->height() - 0)) {
  231. *result = HTBOTTOM;
  232. return true;
  233. }
  234. if (m_widget_title->geometry().contains(QPoint(xPos, yPos)))
  235. {
  236. *result = HTCAPTION;
  237. return false;
  238. }
  239. return false;
  240. }
  241. return false;
  242. }
  243. #define SHADOW_BORDER 6
  244. void QFramelessDialog::paintEvent(QPaintEvent *event)
  245. {
  246. return QDialog::paintEvent(event);
  247. //
  248. // QPainterPath path;
  249. // path.setFillRule(Qt::WindingFill);
  250. // path.addRect(SHADOW_BORDER, SHADOW_BORDER, this->width()-2*SHADOW_BORDER, this->height()-2*SHADOW_BORDER);
  251. //
  252. // QPainter painter(this);
  253. // painter.setRenderHint(QPainter::Antialiasing, true);
  254. // painter.fillPath(path, QBrush(Qt::white));
  255. //
  256. // QColor color(0, 0, 0, 60);
  257. // for(int i=0; i<SHADOW_BORDER; i++)
  258. // {
  259. // QPainterPath path;
  260. // path.setFillRule(Qt::WindingFill);
  261. // path.addRect(SHADOW_BORDER-1-i, SHADOW_BORDER-1-i, this->width()-(SHADOW_BORDER-i)*2, this->height()-(SHADOW_BORDER-i)*2);
  262. // color.setAlpha(40 - i * 7);
  263. // painter.setPen(color);
  264. // painter.drawPath(path);
  265. // }
  266. }
  267. void QFramelessDialog::keyPressEvent(QKeyEvent* e)
  268. {
  269. qDebug()<<e->key();
  270. switch (e->key())
  271. {
  272. case Qt::Key_Return:
  273. break;
  274. case Qt::Key_Enter:
  275. break;
  276. case Qt::Key_Escape:
  277. {
  278. if (m_bMinClose)
  279. break;
  280. }
  281. default:
  282. QDialog::keyPressEvent(e);
  283. }
  284. }

调用示例:

  1. #include <QDialog>
  2. #include "ui_QSubDialog.h"
  3. #include "QFramelessDialog.h"
  4. class QSubDialog : public QFramelessDialog
  5. {
  6. Q_OBJECT
  7. public:
  8. QSubDialog(QWidget *parent = 0);
  9. ~QSubDialog();
  10. private:
  11. Ui::QSubDialog ui;
  12. };
  1. #include "stdafx.h"
  2. #include "QSubDialog.h"
  3. QSubDialog::QSubDialog(QWidget *parent)
  4. : QFramelessDialog(parent)
  5. {
  6. ui.setupUi(this);
  7. FRAMELESS_DIALOG_INIT();
  8. }
  9. QSubDialog::~QSubDialog()
  10. {
  11. }

源代码下载

https://download.csdn.net/download/redchairman/12914480

QT实战派交流群

群号码:1149411109

群名称:Qt实战派学习群

 

 

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

闽ICP备14008679号