赞
踩
本次分享,是基于Qt实现了无边框的窗口,并支持拖动缩放、最大化、最小化、关闭、双击全屏等。
实现无边框其实很简单,一行代码搞定。
setWindowFlag(Qt::FramelessWindowHint);
但是,隐藏了窗口的默认边框,标题栏没了,窗口无法进行拖动缩放了,最小化、最大化、关闭按钮也没有了,因此都需要自己实现。
为了实现无边框窗口到窗口背景的清晰过度,还需要给边框加border线或过度阴影。(本文不提供过度阴影,感兴趣的可以自己去研究,Qt有相关的类可实现)
如果将这个无边框的窗口应用到所有窗口,即如何将无边框窗口作为一个容器使用,也是本文需要解决的问题
首先给大家展示一下效果图。
Qt实战 无边框窗口的实现
- <?xml version="1.0" encoding="UTF-8"?>
- <ui version="4.0">
- <class>SuperWindow</class>
- <widget class="QWidget" name="SuperWindow">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>800</width>
- <height>600</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>SuperWindow</string>
- </property>
- <property name="styleSheet">
- <string notr="true">QWidget#titleBar{
- background-color: rgb(150, 150, 150);
- }
-
- QPushButton[type="btn_win_ctrl"]
- {
- max-width: 20px;
- max-height: 20px;
-
- border: 1px solid rgba(100, 100, 100, 50);
- }
- QPushButton[type="btn_win_ctrl"]:hover
- {
- border: 1px solid blue;
- }
- QPushButton[type="btn_win_ctrl"]:pressed
- {
- border: 2px solid blue;
- }
- QPushButton[type="btn_win_ctrl"]#btnMinimize
- {
- background: center url(:/icons/minium.png) no-repeat;
- }
- QPushButton[type="btn_win_ctrl"]#btnClose
- {
- background: center url(:/icons/close.png) no-repeat;
- }
-
-
- QLabel#lbWinIcon
- {
- max-width: 20px;
- max-height: 20px;
- min-width: 20px;
- min-height: 20px;
- }</string>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <property name="spacing">
- <number>2</number>
- </property>
- <property name="leftMargin">
- <number>3</number>
- </property>
- <property name="topMargin">
- <number>3</number>
- </property>
- <property name="rightMargin">
- <number>3</number>
- </property>
- <property name="bottomMargin">
- <number>3</number>
- </property>
- <item>
- <widget class="QWidget" name="titleBar" native="true">
- <property name="maximumSize">
- <size>
- <width>16777215</width>
- <height>30</height>
- </size>
- </property>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <property name="spacing">
- <number>2</number>
- </property>
- <property name="leftMargin">
- <number>2</number>
- </property>
- <property name="topMargin">
- <number>2</number>
- </property>
- <property name="rightMargin">
- <number>2</number>
- </property>
- <property name="bottomMargin">
- <number>2</number>
- </property>
- <item>
- <widget class="QLabel" name="lbWinIcon">
- <property name="text">
- <string/>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="lbTitle">
- <property name="text">
- <string>标题</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QPushButton" name="btnMinimize">
- <property name="text">
- <string/>
- </property>
- <property name="type" stdset="0">
- <string>btn_win_ctrl</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="btnMaxmize">
- <property name="text">
- <string/>
- </property>
- <property name="type" stdset="0">
- <string>btn_win_ctrl</string>
- </property>
- <property name="bMax" stdset="0">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="btnClose">
- <property name="text">
- <string/>
- </property>
- <property name="type" stdset="0">
- <string>btn_win_ctrl</string>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QWidget" name="wgtContent" native="true">
- <layout class="QGridLayout" name="gridLayout_2">
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item row="0" column="0">
- <layout class="QGridLayout" name="gridContent"/>
- </item>
- </layout>
- </widget>
- </item>
- </layout>
- </widget>
- <resources/>
- <connections/>
- </ui>
- #pragma once
-
- #include "ui_SuperWindow.h"
- #include <QWidget>
-
- QT_BEGIN_NAMESPACE
- namespace Ui { class SuperWindow; }
- QT_END_NAMESPACE
-
- class SuperWindow : public QWidget
- {
- Q_OBJECT
-
- public:
- SuperWindow(QWidget *parent = nullptr);
- ~SuperWindow();
- template<typename T>
- T *CentralWidget()
- {
- if (!m_centralWgt) return nullptr;
- return qobject_cast<T*>(m_centralWgt);
- }
-
- void SetTitle(QString title);
-
- template<typename T>
- static SuperWindow* Create(QWidget* parent = nullptr)
- {
- SuperWindow* fw = new SuperWindow(parent);
- T* centralWgt = new T(fw);
- fw->SetCentralWidget(centralWgt);
- return fw;
- }
-
- protected:
- void mouseDoubleClickEvent(QMouseEvent* event);
- void mousePressEvent(QMouseEvent* event);
- void mouseMoveEvent(QMouseEvent* event);
- void mouseReleaseEvent(QMouseEvent* event);
- void paintEvent(QPaintEvent* e);
- void leaveEvent(QEvent* e);
-
- private:
- void SetCentralWidget(QWidget *widget);
-
- //计算九宫格行
- int row(QPointF pos);
- //计算九宫格列
- int col(QPointF pos);
- //点击区域 相对于九宫格
- int moveArea(QPointF pos);
- void setMouseStyle(int moveArea);
-
- private slots:
- void OnMaxmized();
-
- private:
- Ui::SuperWindow *ui;
- QWidget* m_centralWgt{ nullptr };
-
- bool m_bPressed{ false };
- bool m_bResizing{false};
- int m_flag;
- QPoint curPos;
- int m_nBorder{ 3 };
- };
-
- #include "SuperWindow.h"
-
- #include <QMouseEvent>
- #include <QPainter>
-
- SuperWindow::SuperWindow(QWidget* parent)
- : QWidget(parent)
- , ui(new Ui::SuperWindow)
- {
- ui->setupUi(this);
- setWindowFlag(Qt::FramelessWindowHint);
- setMouseTracking(true);
-
- ui->btnMaxmize->setIcon(QIcon(":/icons/maxsize.png"));
-
-
- for (auto obj : children()) {
- auto wgt = qobject_cast<QWidget*>(obj);
- if (wgt) wgt->setMouseTracking(true);
- }
-
- connect(ui->btnMinimize, &QPushButton::clicked, this, &SuperWindow::showMinimized);
- connect(ui->btnMaxmize, &QPushButton::clicked, this, &SuperWindow::OnMaxmized);
- connect(ui->btnClose, &QPushButton::clicked, this, &SuperWindow::close);
- }
-
- SuperWindow::~SuperWindow()
- {
- delete ui;
- }
-
- void SuperWindow::SetTitle(QString title)
- {
- ui->lbTitle->setText(title);
- setWindowTitle(title);
- }
-
- void SuperWindow::SetCentralWidget(QWidget *widget)
- {
- if (m_centralWgt) return;
- m_centralWgt = widget;
- ui->gridContent->addWidget(widget);
- }
-
- void SuperWindow::mouseDoubleClickEvent(QMouseEvent* event)
- {
- if (event->button() == Qt::LeftButton)
- {
- if (ui->titleBar->geometry().contains(event->pos()))
- {
- OnMaxmized();
- }
- }
- }
-
- void SuperWindow::mousePressEvent(QMouseEvent* event)
- {
- if (event->button() == Qt::LeftButton)
- {
- if (ui->titleBar->geometry().contains(event->pos()) &&
- this->cursor() == Qt::ArrowCursor)
- {
- m_bPressed = true;
- curPos = event->globalPosition().toPoint();
- }
- else if (m_flag != 22)
- {
- m_bResizing = true;
- curPos = event->globalPosition().toPoint();
- }
- }
- }
-
- void SuperWindow::mouseMoveEvent(QMouseEvent* event)
- {
- if (m_bPressed) //如果鼠标左键按下
- {
- QPoint tmpPos = event->globalPosition().toPoint();
- QPoint delta = tmpPos - curPos;
- move(pos() + delta);
- curPos = tmpPos;
- }
- else
- {
- if (!m_bResizing)
- {
- m_flag = moveArea(event->pos());
- setMouseStyle(m_flag);
- return;
- }
-
- qDebug() << "resizing " << event->pos();
-
- QPoint tmpPos = event->globalPosition().toPoint();
- QPoint delta = tmpPos - curPos;
- curPos = tmpPos;
-
- //记录窗体当前位置
- QRect rect = geometry();
- //鼠标左键处于拖拽拉伸区域
- //m_flag为鼠标点击左键时 鼠标样式状态
- switch (m_flag)
- {
- case 11: rect.setTopLeft(rect.topLeft() + delta); break; //左上角
- case 13: rect.setTopRight(rect.topRight() + delta); break; //右上角
- case 31: rect.setBottomLeft(rect.bottomLeft() + delta); break; //左下角
- case 33: rect.setBottomRight(rect.bottomRight() + delta); break; //右下角
- case 12: rect.setTop(rect.top() + delta.y()); break; //上
- case 21: rect.setLeft(rect.left() + delta.x()); break; //左
- case 23: rect.setRight(rect.right() + delta.x()); break; //右
- case 32: rect.setBottom(rect.bottom() + delta.y()); break; //下
- default: break;
- }
- this->setGeometry(rect);
- }
- }
-
- void SuperWindow::mouseReleaseEvent(QMouseEvent* event)
- {
- Q_UNUSED(event);
- if (event->button() == Qt::LeftButton)
- {
- if (m_bPressed) m_bPressed = false;
-
- if (m_bResizing)
- {
- m_bResizing = false;
- m_flag = 22;
- update();
- }
- }
- }
-
- void SuperWindow::paintEvent(QPaintEvent* e)
- {
- QPainter painter(this);
- {
- painter.save();
- QRect rect(m_nBorder/2, m_nBorder/2, width()-m_nBorder/2, height()-m_nBorder/2);
-
- QPen pen;
- pen.setColor(Qt::lightGray);
- pen.setWidth(m_nBorder);
- painter.setPen(pen);
-
- painter.drawRect(rect);
- painter.restore();
- }
-
- if (m_flag == 22) return;
- else
- {
- QBrush brush;
- brush.setColor(QColor(73, 95, 22, 150));//设置颜色
- brush.setStyle(Qt::SolidPattern);
- painter.setBrush(brush);
- painter.setPen(Qt::NoPen);
-
- switch (m_flag)
- {
- case 12:
- {
- QRect rect(0, 0, width(), m_nBorder);
- painter.drawRect(rect);
- break;
- }
- case 21:
- {
- QRect rect(0, 0, m_nBorder, height());
- painter.drawRect(rect);
- break;
- }
- case 23:
- {
- QRect rect(width()-m_nBorder, 0, m_nBorder, height());
- painter.drawRect(rect);
- break;
- }
- case 32:
- {
- QRect rect(0, height()-m_nBorder, width(), m_nBorder);
- painter.drawRect(rect);
- break;
- }
- case 11:
- {
- QRect rect(0, 0, width(), m_nBorder);
- painter.drawRect(rect);
- rect = QRect(0, 0, m_nBorder, height());
- painter.drawRect(rect);
- break;
- }
- case 13:
- {
- QRect rect(0, 0, width(), m_nBorder);
- painter.drawRect(rect);
- rect = QRect(width()-m_nBorder, 0, m_nBorder, height());
- painter.drawRect(rect);
- break;
- }
- case 31:
- {
- QRect rect(0, 0, m_nBorder, height());
- painter.drawRect(rect);
- rect = QRect(0, height()-m_nBorder, width(), m_nBorder);
- painter.drawRect(rect);
- break;
- }
- case 33:
- {
- QRect rect(0, height()-m_nBorder, width(), m_nBorder);
- painter.drawRect(rect);
- rect = QRect(width()-m_nBorder, 0, m_nBorder, height());
- painter.drawRect(rect);
- break;
- }
- default:
- break;
- }
- }
- }
-
- void SuperWindow::leaveEvent(QEvent *e)
- {
- Q_UNUSED(e);
- m_flag = 22;
- }
-
- int SuperWindow::row(QPointF pos)
- {
- if (pos.y() < m_nBorder)
- return 10;
- else if (pos.y() > height() - m_nBorder)
- return 30;
- else
- return 20;
- }
-
- int SuperWindow::col(QPointF pos)
- {
- if (pos.x() < m_nBorder)
- return 1;
- else if (pos.x() > width() - m_nBorder)
- return 3;
- else
- return 2;
- }
-
- int SuperWindow::moveArea(QPointF pos)
- {
- return row(pos) + col(pos);
- }
-
- void SuperWindow::setMouseStyle(int moveArea)
- {
- switch (moveArea)
- {
- case 11: setCursor(Qt::SizeFDiagCursor); break;
- case 12: setCursor(Qt::SizeVerCursor); break;
- case 13: setCursor(Qt::SizeBDiagCursor); break;
- case 21: setCursor(Qt::SizeHorCursor); break;
- case 22:
- {
- if (!m_bPressed && !m_bResizing)
- setCursor(Qt::ArrowCursor);
- break;
- }
- case 23: setCursor(Qt::SizeHorCursor); break;
- case 31: setCursor(Qt::SizeBDiagCursor); break;
- case 32: setCursor(Qt::SizeVerCursor); break;
- case 33: setCursor(Qt::SizeFDiagCursor); break;
- default: setCursor(Qt::ArrowCursor); break;
- }
- }
-
- void SuperWindow::OnMaxmized()
- {
- if (this->isMaximized())
- {
- this->showNormal();
- ui->btnMaxmize->setIcon(QIcon(":/icons/maxsize.png"));
- }
- else
- {
- this->showMaximized();
- ui->btnMaxmize->setIcon(QIcon(":/icons/normal.png"));
- }
- }
- #include "MainWin.h"
- #include "SuperWindow.h"
-
- #include <QApplication>
-
- int main(int argc, char *argv[])
- {
- QApplication a(argc, argv);
-
- SuperWindow* win = SuperWindow::Create<MainWin>(nullptr);
- win->show();
-
- MainWin* mw = win->CentralWidget<MainWin>();
- if (!mw) qDebug() << "not nullptr";
- else mw->setVisible(false);
-
- return a.exec();
- }
对于MainWin的实现,这里就不在放代码了,只要是集成QWidget的窗口即可。
如果我的分享,帮助了您,不要忘记点赞、评论和收藏。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。