当前位置:   article > 正文

Qt实战 无边框窗口的实现_qt无边框窗口

qt无边框窗口

本次分享,是基于Qt实现了无边框的窗口,并支持拖动缩放、最大化、最小化、关闭、双击全屏等。

实现无边框其实很简单,一行代码搞定。

setWindowFlag(Qt::FramelessWindowHint);

但是,隐藏了窗口的默认边框,标题栏没了,窗口无法进行拖动缩放了,最小化最大化关闭按钮也没有了,因此都需要自己实现。

为了实现无边框窗口到窗口背景的清晰过度,还需要给边框加border线或过度阴影。(本文不提供过度阴影,感兴趣的可以自己去研究,Qt有相关的类可实现)

如果将这个无边框的窗口应用到所有窗口,即如何将无边框窗口作为一个容器使用,也是本文需要解决的问题

首先给大家展示一下效果图。

Qt实战 无边框窗口的实现

无边框窗口类实现

SuperWindow.ui

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <ui version="4.0">
  3. <class>SuperWindow</class>
  4. <widget class="QWidget" name="SuperWindow">
  5. <property name="geometry">
  6. <rect>
  7. <x>0</x>
  8. <y>0</y>
  9. <width>800</width>
  10. <height>600</height>
  11. </rect>
  12. </property>
  13. <property name="windowTitle">
  14. <string>SuperWindow</string>
  15. </property>
  16. <property name="styleSheet">
  17. <string notr="true">QWidget#titleBar{
  18. background-color: rgb(150, 150, 150);
  19. }
  20. QPushButton[type=&quot;btn_win_ctrl&quot;]
  21. {
  22. max-width: 20px;
  23. max-height: 20px;
  24. border: 1px solid rgba(100, 100, 100, 50);
  25. }
  26. QPushButton[type=&quot;btn_win_ctrl&quot;]:hover
  27. {
  28. border: 1px solid blue;
  29. }
  30. QPushButton[type=&quot;btn_win_ctrl&quot;]:pressed
  31. {
  32. border: 2px solid blue;
  33. }
  34. QPushButton[type=&quot;btn_win_ctrl&quot;]#btnMinimize
  35. {
  36. background: center url(:/icons/minium.png) no-repeat;
  37. }
  38. QPushButton[type=&quot;btn_win_ctrl&quot;]#btnClose
  39. {
  40. background: center url(:/icons/close.png) no-repeat;
  41. }
  42. QLabel#lbWinIcon
  43. {
  44. max-width: 20px;
  45. max-height: 20px;
  46. min-width: 20px;
  47. min-height: 20px;
  48. }</string>
  49. </property>
  50. <layout class="QVBoxLayout" name="verticalLayout">
  51. <property name="spacing">
  52. <number>2</number>
  53. </property>
  54. <property name="leftMargin">
  55. <number>3</number>
  56. </property>
  57. <property name="topMargin">
  58. <number>3</number>
  59. </property>
  60. <property name="rightMargin">
  61. <number>3</number>
  62. </property>
  63. <property name="bottomMargin">
  64. <number>3</number>
  65. </property>
  66. <item>
  67. <widget class="QWidget" name="titleBar" native="true">
  68. <property name="maximumSize">
  69. <size>
  70. <width>16777215</width>
  71. <height>30</height>
  72. </size>
  73. </property>
  74. <layout class="QHBoxLayout" name="horizontalLayout">
  75. <property name="spacing">
  76. <number>2</number>
  77. </property>
  78. <property name="leftMargin">
  79. <number>2</number>
  80. </property>
  81. <property name="topMargin">
  82. <number>2</number>
  83. </property>
  84. <property name="rightMargin">
  85. <number>2</number>
  86. </property>
  87. <property name="bottomMargin">
  88. <number>2</number>
  89. </property>
  90. <item>
  91. <widget class="QLabel" name="lbWinIcon">
  92. <property name="text">
  93. <string/>
  94. </property>
  95. </widget>
  96. </item>
  97. <item>
  98. <widget class="QLabel" name="lbTitle">
  99. <property name="text">
  100. <string>标题</string>
  101. </property>
  102. </widget>
  103. </item>
  104. <item>
  105. <spacer name="horizontalSpacer">
  106. <property name="orientation">
  107. <enum>Qt::Horizontal</enum>
  108. </property>
  109. <property name="sizeHint" stdset="0">
  110. <size>
  111. <width>40</width>
  112. <height>20</height>
  113. </size>
  114. </property>
  115. </spacer>
  116. </item>
  117. <item>
  118. <widget class="QPushButton" name="btnMinimize">
  119. <property name="text">
  120. <string/>
  121. </property>
  122. <property name="type" stdset="0">
  123. <string>btn_win_ctrl</string>
  124. </property>
  125. </widget>
  126. </item>
  127. <item>
  128. <widget class="QPushButton" name="btnMaxmize">
  129. <property name="text">
  130. <string/>
  131. </property>
  132. <property name="type" stdset="0">
  133. <string>btn_win_ctrl</string>
  134. </property>
  135. <property name="bMax" stdset="0">
  136. <bool>false</bool>
  137. </property>
  138. </widget>
  139. </item>
  140. <item>
  141. <widget class="QPushButton" name="btnClose">
  142. <property name="text">
  143. <string/>
  144. </property>
  145. <property name="type" stdset="0">
  146. <string>btn_win_ctrl</string>
  147. </property>
  148. </widget>
  149. </item>
  150. </layout>
  151. </widget>
  152. </item>
  153. <item>
  154. <widget class="QWidget" name="wgtContent" native="true">
  155. <layout class="QGridLayout" name="gridLayout_2">
  156. <property name="leftMargin">
  157. <number>0</number>
  158. </property>
  159. <property name="topMargin">
  160. <number>0</number>
  161. </property>
  162. <property name="rightMargin">
  163. <number>0</number>
  164. </property>
  165. <property name="bottomMargin">
  166. <number>0</number>
  167. </property>
  168. <item row="0" column="0">
  169. <layout class="QGridLayout" name="gridContent"/>
  170. </item>
  171. </layout>
  172. </widget>
  173. </item>
  174. </layout>
  175. </widget>
  176. <resources/>
  177. <connections/>
  178. </ui>

SuperWindow.h

  1. #pragma once
  2. #include "ui_SuperWindow.h"
  3. #include <QWidget>
  4. QT_BEGIN_NAMESPACE
  5. namespace Ui { class SuperWindow; }
  6. QT_END_NAMESPACE
  7. class SuperWindow : public QWidget
  8. {
  9. Q_OBJECT
  10. public:
  11. SuperWindow(QWidget *parent = nullptr);
  12. ~SuperWindow();
  13. template<typename T>
  14. T *CentralWidget()
  15. {
  16. if (!m_centralWgt) return nullptr;
  17. return qobject_cast<T*>(m_centralWgt);
  18. }
  19. void SetTitle(QString title);
  20. template<typename T>
  21. static SuperWindow* Create(QWidget* parent = nullptr)
  22. {
  23. SuperWindow* fw = new SuperWindow(parent);
  24. T* centralWgt = new T(fw);
  25. fw->SetCentralWidget(centralWgt);
  26. return fw;
  27. }
  28. protected:
  29. void mouseDoubleClickEvent(QMouseEvent* event);
  30. void mousePressEvent(QMouseEvent* event);
  31. void mouseMoveEvent(QMouseEvent* event);
  32. void mouseReleaseEvent(QMouseEvent* event);
  33. void paintEvent(QPaintEvent* e);
  34. void leaveEvent(QEvent* e);
  35. private:
  36. void SetCentralWidget(QWidget *widget);
  37. //计算九宫格行
  38. int row(QPointF pos);
  39. //计算九宫格列
  40. int col(QPointF pos);
  41. //点击区域 相对于九宫格
  42. int moveArea(QPointF pos);
  43. void setMouseStyle(int moveArea);
  44. private slots:
  45. void OnMaxmized();
  46. private:
  47. Ui::SuperWindow *ui;
  48. QWidget* m_centralWgt{ nullptr };
  49. bool m_bPressed{ false };
  50. bool m_bResizing{false};
  51. int m_flag;
  52. QPoint curPos;
  53. int m_nBorder{ 3 };
  54. };

SuperWindow.cpp

  1. #include "SuperWindow.h"
  2. #include <QMouseEvent>
  3. #include <QPainter>
  4. SuperWindow::SuperWindow(QWidget* parent)
  5. : QWidget(parent)
  6. , ui(new Ui::SuperWindow)
  7. {
  8. ui->setupUi(this);
  9. setWindowFlag(Qt::FramelessWindowHint);
  10. setMouseTracking(true);
  11. ui->btnMaxmize->setIcon(QIcon(":/icons/maxsize.png"));
  12. for (auto obj : children()) {
  13. auto wgt = qobject_cast<QWidget*>(obj);
  14. if (wgt) wgt->setMouseTracking(true);
  15. }
  16. connect(ui->btnMinimize, &QPushButton::clicked, this, &SuperWindow::showMinimized);
  17. connect(ui->btnMaxmize, &QPushButton::clicked, this, &SuperWindow::OnMaxmized);
  18. connect(ui->btnClose, &QPushButton::clicked, this, &SuperWindow::close);
  19. }
  20. SuperWindow::~SuperWindow()
  21. {
  22. delete ui;
  23. }
  24. void SuperWindow::SetTitle(QString title)
  25. {
  26. ui->lbTitle->setText(title);
  27. setWindowTitle(title);
  28. }
  29. void SuperWindow::SetCentralWidget(QWidget *widget)
  30. {
  31. if (m_centralWgt) return;
  32. m_centralWgt = widget;
  33. ui->gridContent->addWidget(widget);
  34. }
  35. void SuperWindow::mouseDoubleClickEvent(QMouseEvent* event)
  36. {
  37. if (event->button() == Qt::LeftButton)
  38. {
  39. if (ui->titleBar->geometry().contains(event->pos()))
  40. {
  41. OnMaxmized();
  42. }
  43. }
  44. }
  45. void SuperWindow::mousePressEvent(QMouseEvent* event)
  46. {
  47. if (event->button() == Qt::LeftButton)
  48. {
  49. if (ui->titleBar->geometry().contains(event->pos()) &&
  50. this->cursor() == Qt::ArrowCursor)
  51. {
  52. m_bPressed = true;
  53. curPos = event->globalPosition().toPoint();
  54. }
  55. else if (m_flag != 22)
  56. {
  57. m_bResizing = true;
  58. curPos = event->globalPosition().toPoint();
  59. }
  60. }
  61. }
  62. void SuperWindow::mouseMoveEvent(QMouseEvent* event)
  63. {
  64. if (m_bPressed) //如果鼠标左键按下
  65. {
  66. QPoint tmpPos = event->globalPosition().toPoint();
  67. QPoint delta = tmpPos - curPos;
  68. move(pos() + delta);
  69. curPos = tmpPos;
  70. }
  71. else
  72. {
  73. if (!m_bResizing)
  74. {
  75. m_flag = moveArea(event->pos());
  76. setMouseStyle(m_flag);
  77. return;
  78. }
  79. qDebug() << "resizing " << event->pos();
  80. QPoint tmpPos = event->globalPosition().toPoint();
  81. QPoint delta = tmpPos - curPos;
  82. curPos = tmpPos;
  83. //记录窗体当前位置
  84. QRect rect = geometry();
  85. //鼠标左键处于拖拽拉伸区域
  86. //m_flag为鼠标点击左键时 鼠标样式状态
  87. switch (m_flag)
  88. {
  89. case 11: rect.setTopLeft(rect.topLeft() + delta); break; //左上角
  90. case 13: rect.setTopRight(rect.topRight() + delta); break; //右上角
  91. case 31: rect.setBottomLeft(rect.bottomLeft() + delta); break; //左下角
  92. case 33: rect.setBottomRight(rect.bottomRight() + delta); break; //右下角
  93. case 12: rect.setTop(rect.top() + delta.y()); break; //上
  94. case 21: rect.setLeft(rect.left() + delta.x()); break; //左
  95. case 23: rect.setRight(rect.right() + delta.x()); break; //右
  96. case 32: rect.setBottom(rect.bottom() + delta.y()); break; //下
  97. default: break;
  98. }
  99. this->setGeometry(rect);
  100. }
  101. }
  102. void SuperWindow::mouseReleaseEvent(QMouseEvent* event)
  103. {
  104. Q_UNUSED(event);
  105. if (event->button() == Qt::LeftButton)
  106. {
  107. if (m_bPressed) m_bPressed = false;
  108. if (m_bResizing)
  109. {
  110. m_bResizing = false;
  111. m_flag = 22;
  112. update();
  113. }
  114. }
  115. }
  116. void SuperWindow::paintEvent(QPaintEvent* e)
  117. {
  118. QPainter painter(this);
  119. {
  120. painter.save();
  121. QRect rect(m_nBorder/2, m_nBorder/2, width()-m_nBorder/2, height()-m_nBorder/2);
  122. QPen pen;
  123. pen.setColor(Qt::lightGray);
  124. pen.setWidth(m_nBorder);
  125. painter.setPen(pen);
  126. painter.drawRect(rect);
  127. painter.restore();
  128. }
  129. if (m_flag == 22) return;
  130. else
  131. {
  132. QBrush brush;
  133. brush.setColor(QColor(73, 95, 22, 150));//设置颜色
  134. brush.setStyle(Qt::SolidPattern);
  135. painter.setBrush(brush);
  136. painter.setPen(Qt::NoPen);
  137. switch (m_flag)
  138. {
  139. case 12:
  140. {
  141. QRect rect(0, 0, width(), m_nBorder);
  142. painter.drawRect(rect);
  143. break;
  144. }
  145. case 21:
  146. {
  147. QRect rect(0, 0, m_nBorder, height());
  148. painter.drawRect(rect);
  149. break;
  150. }
  151. case 23:
  152. {
  153. QRect rect(width()-m_nBorder, 0, m_nBorder, height());
  154. painter.drawRect(rect);
  155. break;
  156. }
  157. case 32:
  158. {
  159. QRect rect(0, height()-m_nBorder, width(), m_nBorder);
  160. painter.drawRect(rect);
  161. break;
  162. }
  163. case 11:
  164. {
  165. QRect rect(0, 0, width(), m_nBorder);
  166. painter.drawRect(rect);
  167. rect = QRect(0, 0, m_nBorder, height());
  168. painter.drawRect(rect);
  169. break;
  170. }
  171. case 13:
  172. {
  173. QRect rect(0, 0, width(), m_nBorder);
  174. painter.drawRect(rect);
  175. rect = QRect(width()-m_nBorder, 0, m_nBorder, height());
  176. painter.drawRect(rect);
  177. break;
  178. }
  179. case 31:
  180. {
  181. QRect rect(0, 0, m_nBorder, height());
  182. painter.drawRect(rect);
  183. rect = QRect(0, height()-m_nBorder, width(), m_nBorder);
  184. painter.drawRect(rect);
  185. break;
  186. }
  187. case 33:
  188. {
  189. QRect rect(0, height()-m_nBorder, width(), m_nBorder);
  190. painter.drawRect(rect);
  191. rect = QRect(width()-m_nBorder, 0, m_nBorder, height());
  192. painter.drawRect(rect);
  193. break;
  194. }
  195. default:
  196. break;
  197. }
  198. }
  199. }
  200. void SuperWindow::leaveEvent(QEvent *e)
  201. {
  202. Q_UNUSED(e);
  203. m_flag = 22;
  204. }
  205. int SuperWindow::row(QPointF pos)
  206. {
  207. if (pos.y() < m_nBorder)
  208. return 10;
  209. else if (pos.y() > height() - m_nBorder)
  210. return 30;
  211. else
  212. return 20;
  213. }
  214. int SuperWindow::col(QPointF pos)
  215. {
  216. if (pos.x() < m_nBorder)
  217. return 1;
  218. else if (pos.x() > width() - m_nBorder)
  219. return 3;
  220. else
  221. return 2;
  222. }
  223. int SuperWindow::moveArea(QPointF pos)
  224. {
  225. return row(pos) + col(pos);
  226. }
  227. void SuperWindow::setMouseStyle(int moveArea)
  228. {
  229. switch (moveArea)
  230. {
  231. case 11: setCursor(Qt::SizeFDiagCursor); break;
  232. case 12: setCursor(Qt::SizeVerCursor); break;
  233. case 13: setCursor(Qt::SizeBDiagCursor); break;
  234. case 21: setCursor(Qt::SizeHorCursor); break;
  235. case 22:
  236. {
  237. if (!m_bPressed && !m_bResizing)
  238. setCursor(Qt::ArrowCursor);
  239. break;
  240. }
  241. case 23: setCursor(Qt::SizeHorCursor); break;
  242. case 31: setCursor(Qt::SizeBDiagCursor); break;
  243. case 32: setCursor(Qt::SizeVerCursor); break;
  244. case 33: setCursor(Qt::SizeFDiagCursor); break;
  245. default: setCursor(Qt::ArrowCursor); break;
  246. }
  247. }
  248. void SuperWindow::OnMaxmized()
  249. {
  250. if (this->isMaximized())
  251. {
  252. this->showNormal();
  253. ui->btnMaxmize->setIcon(QIcon(":/icons/maxsize.png"));
  254. }
  255. else
  256. {
  257. this->showMaximized();
  258. ui->btnMaxmize->setIcon(QIcon(":/icons/normal.png"));
  259. }
  260. }

main.cpp

  1. #include "MainWin.h"
  2. #include "SuperWindow.h"
  3. #include <QApplication>
  4. int main(int argc, char *argv[])
  5. {
  6. QApplication a(argc, argv);
  7. SuperWindow* win = SuperWindow::Create<MainWin>(nullptr);
  8. win->show();
  9. MainWin* mw = win->CentralWidget<MainWin>();
  10. if (!mw) qDebug() << "not nullptr";
  11. else mw->setVisible(false);
  12. return a.exec();
  13. }

对于MainWin的实现,这里就不在放代码了,只要是集成QWidget的窗口即可。

如果我的分享,帮助了您,不要忘记点赞、评论和收藏。

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

闽ICP备14008679号