1、隐藏标题栏
窗口自带的标题栏和按钮,很难满足美化的需求,所以就需要将其隐藏:
# 隐藏标题栏
self.setWindowFlags(Qt.WindowType.FramelessWindowHint)
self.setAttribute(Qt.WA_TranslucentBackground)
代码很简单,但是这样就会失去最大化、窗口拖动、窗口调整大小等功能,需要我们手动实现。
2、最小化、最大化、关闭
这三个是窗口最基础的功能,直接调用窗口本身自带的函数即可,需要我们使用三个按钮实现:
图标资源可以去阿里巴巴矢量图库下载:iconfont-阿里巴巴矢量图标库
代码实现三个按钮功能:
# 最小化
self.ui.btn_min.clicked.connect(self.showMinimized)
# 关闭
self.ui.btn_close.clicked.connect(self.close)
# 最大化
self.ui.btn_max.clicked.connect(self.showMaximized)
这是QMainWindow自带的三个功能,但是最大化功能需要自己改造一下,不然最大化之后,再次点击无法返回原来大小。
将最大化按钮绑定为自定义的最大化函数,就可以实现最大化和原始大小之间的切换:
self.ui.btn_max.clicked.connect(self.maximize_restore)
# 全局变量
GLOBAL_STATE = False
def maximize_restore(self):
global GLOBAL_STATE
status = GLOBAL_STATE
if status == False:
self.showMaximized()
GLOBAL_STATE = True
else:
GLOBAL_STATE = False
self.showNormal()
self.resize(self.width() + 1, self.height() + 1)
双击实现最大化:
def double_click_max(event):
# 双击切换最大化
if event.type() == QEvent.MouseButtonDblClick:
QTimer.singleShot(250, lambda: UIFunctions.maximize_restore(self))
self.ui.top_bar.mouseDoubleClickEvent = double_click_max
通过将双击实现最大化的函数绑定到UI界面中的top_bar,top_bar是使用QFrame绘制的一块区域,用来规定双击最大化的区域,也可以使用其他控件。
3、窗口拖动
窗口拖动需要重写QMainWindow的一些函数:
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton and self.ui.top_bar.geometry().contains(event.position().toPoint()):
self.old_pos = event.globalPosition().toPoint()
def mouseMoveEvent(self, event):
if self.old_pos is not None:
delta = QPoint(event.globalPosition().toPoint() - self.old_pos)
self.move(self.x() + delta.x(), self.y() + delta.y())
self.old_pos = event.globalPosition().toPoint()
def mouseReleaseEvent(self, event):
self.old_pos = None
需要根据自己的UI界面,修改self.ui.top_bar,其作用是规定界面中哪一部分可以被拖动,可以是QFrame或者其他控件。
4、窗口边缘调整窗口大小
实现这个功能还是比较麻烦的,需要自己定义一个组件类CustomGrip:
from PySide6.QtCore import *
from PySide6.QtGui import *
from PySide6.QtWidgets import *
"""
自定义CustomGrip控件,实现用户通过拖动窗口的边缘来调整窗口的大小
"""
class CustomGrip(QWidget):
def __init__(self, parent, position, disable_color = False):
# 设置UI
QWidget.__init__(self)
self.parent = parent
self.setParent(parent)
self.wi = Widgets()
if position == Qt.TopEdge:
self.wi.top(self)
self.setGeometry(0, 0, self.parent.width(), 10)
self.setMaximumHeight(10)
top_left = QSizeGrip(self.wi.top_left)
top_right = QSizeGrip(self.wi.top_right)
def resize_top(event):
delta = event.pos()
height = max(self.parent.minimumHeight(), self.parent.height() - delta.y())
geo = self.parent.geometry()
geo.setTop(geo.bottom() - height)
self.parent.setGeometry(geo)
event.accept()
self.wi.top.mouseMoveEvent = resize_top
if disable_color:
self.wi.top_left.setStyleSheet("background: transparent")
self.wi.top_right.setStyleSheet("background: transparent")
self.wi.top.setStyleSheet("background: transparent")
elif position == Qt.BottomEdge:
self.wi.bottom(self)
self.setGeometry(0, self.parent.height() - 10, self.parent.width(), 10)
self.setMaximumHeight(10)
self.bottom_left = QSizeGrip(self.wi.bottom_left)
self.bottom_right = QSizeGrip(self.wi.bottom_right)
def resize_bottom(event):
delta = event.pos()
height = max(self.parent.minimumHeight(), self.parent.height() + delta.y())
self.parent.resize(self.parent.width(), height)
event.accept()
self.wi.bottom.mouseMoveEvent = resize_bottom
if disable_color:
self.wi.bottom_left.setStyleSheet("background: transparent")
self.wi.bottom_right.setStyleSheet("background: transparent")
self.wi.bottom.setStyleSheet("background: transparent")
elif position == Qt.LeftEdge:
self.wi.left(self)
self.setGeometry(0, 10, 10, self.parent.height())
self.setMaximumWidth(10)
def resize_left(event):
delta = event.pos()
width = max(self.parent.minimumWidth(), self.parent.width() - delta.x())
geo = self.parent.geometry()
geo.setLeft(geo.right() - width)
self.parent.setGeometry(geo)
event.accept()
self.wi.leftgrip.mouseMoveEvent = resize_left
if disable_color:
self.wi.leftgrip.setStyleSheet("background: transparent")
elif position == Qt.RightEdge:
self.wi.right(self)
self.setGeometry(self.parent.width() - 10, 10, 10, self.parent.height())
self.setMaximumWidth(10)
def resize_right(event):
delta = event.pos()
width = max(self.parent.minimumWidth(), self.parent.width() + delta.x())
self.parent.resize(width, self.parent.height())
event.accept()
self.wi.rightgrip.mouseMoveEvent = resize_right
if disable_color:
self.wi.rightgrip.setStyleSheet("background: transparent")
def mouseReleaseEvent(self, event):
self.mousePos = None
def resizeEvent(self, event):
if hasattr(self.wi, 'container_top'):
self.wi.container_top.setGeometry(0, 0, self.width(), 10)
elif hasattr(self.wi, 'container_bottom'):
self.wi.container_bottom.setGeometry(0, 0, self.width(), 10)
elif hasattr(self.wi, 'leftgrip'):
self.wi.leftgrip.setGeometry(0, 0, 10, self.height() - 20)
elif hasattr(self.wi, 'rightgrip'):
self.wi.rightgrip.setGeometry(0, 0, 10, self.height() - 20)
class Widgets(object):
def top(self, Form):
if not Form.objectName():
Form.setObjectName(u"Form")
self.container_top = QFrame(Form)
self.container_top.setObjectName(u"container_top")
self.container_top.setGeometry(QRect(0, 0, 500, 10))
self.container_top.setMinimumSize(QSize(0, 10))
self.container_top.setMaximumSize(QSize(16777215, 10))
self.container_top.setFrameShape(QFrame.NoFrame)
self.container_top.setFrameShadow(QFrame.Raised)
self.top_layout = QHBoxLayout(self.container_top)
self.top_layout.setSpacing(0)
self.top_layout.setObjectName(u"top_layout")
self.top_layout.setContentsMargins(0, 0, 0, 0)
self.top_left = QFrame(self.container_top)
self.top_left.setObjectName(u"top_left")
self.top_left.setMinimumSize(QSize(10, 10))
self.top_left.setMaximumSize(QSize(10, 10))
self.top_left.setCursor(QCursor(Qt.SizeFDiagCursor))
self.top_left.setStyleSheet(u"background-color: rgb(33, 37, 43);")
self.top_left.setFrameShape(QFrame.NoFrame)
self.top_left.setFrameShadow(QFrame.Raised)
self.top_layout.addWidget(self.top_left)
self.top = QFrame(self.container_top)
self.top.setObjectName(u"top")
self.top.setCursor(QCursor(Qt.SizeVerCursor))
self.top.setStyleSheet(u"background-color: rgb(85, 255, 255);")
self.top.setFrameShape(QFrame.NoFrame)
self.top.setFrameShadow(QFrame.Raised)
self.top_layout.addWidget(self.top)
self.top_right = QFrame(self.container_top)
self.top_right.setObjectName(u"top_right")
self.top_right.setMinimumSize(QSize(10, 10))
self.top_right.setMaximumSize(QSize(10, 10))
self.top_right.setCursor(QCursor(Qt.SizeBDiagCursor))
self.top_right.setStyleSheet(u"background-color: rgb(33, 37, 43);")
self.top_right.setFrameShape(QFrame.NoFrame)
self.top_right.setFrameShadow(QFrame.Raised)
self.top_layout.addWidget(self.top_right)
def bottom(self, Form):
if not Form.objectName():
Form.setObjectName(u"Form")
self.container_bottom = QFrame(Form)
self.container_bottom.setObjectName(u"container_bottom")
self.container_bottom.setGeometry(QRect(0, 0, 500, 10))
self.container_bottom.setMinimumSize(QSize(0, 10))
self.container_bottom.setMaximumSize(QSize(16777215, 10))
self.container_bottom.setFrameShape(QFrame.NoFrame)
self.container_bottom.setFrameShadow(QFrame.Raised)
self.bottom_layout = QHBoxLayout(self.container_bottom)
self.bottom_layout.setSpacing(0)
self.bottom_layout.setObjectName(u"bottom_layout")
self.bottom_layout.setContentsMargins(0, 0, 0, 0)
self.bottom_left = QFrame(self.container_bottom)
self.bottom_left.setObjectName(u"bottom_left")
self.bottom_left.setMinimumSize(QSize(10, 10))
self.bottom_left.setMaximumSize(QSize(10, 10))
self.bottom_left.setCursor(QCursor(Qt.SizeBDiagCursor))
self.bottom_left.setStyleSheet(u"background-color: rgb(33, 37, 43);")
self.bottom_left.setFrameShape(QFrame.NoFrame)
self.bottom_left.setFrameShadow(QFrame.Raised)
self.bottom_layout.addWidget(self.bottom_left)
self.bottom = QFrame(self.container_bottom)
self.bottom.setObjectName(u"bottom")
self.bottom.setCursor(QCursor(Qt.SizeVerCursor))
self.bottom.setStyleSheet(u"background-color: rgb(85, 170, 0);")
self.bottom.setFrameShape(QFrame.NoFrame)
self.bottom.setFrameShadow(QFrame.Raised)
self.bottom_layout.addWidget(self.bottom)
self.bottom_right = QFrame(self.container_bottom)
self.bottom_right.setObjectName(u"bottom_right")
self.bottom_right.setMinimumSize(QSize(10, 10))
self.bottom_right.setMaximumSize(QSize(10, 10))
self.bottom_right.setCursor(QCursor(Qt.SizeFDiagCursor))
self.bottom_right.setStyleSheet(u"background-color: rgb(33, 37, 43);")
self.bottom_right.setFrameShape(QFrame.NoFrame)
self.bottom_right.setFrameShadow(QFrame.Raised)
self.bottom_layout.addWidget(self.bottom_right)
def left(self, Form):
if not Form.objectName():
Form.setObjectName(u"Form")
self.leftgrip = QFrame(Form)
self.leftgrip.setObjectName(u"left")
self.leftgrip.setGeometry(QRect(0, 10, 10, 480))
self.leftgrip.setMinimumSize(QSize(10, 0))
self.leftgrip.setCursor(QCursor(Qt.SizeHorCursor))
self.leftgrip.setStyleSheet(u"background-color: rgb(255, 121, 198);")
self.leftgrip.setFrameShape(QFrame.NoFrame)
self.leftgrip.setFrameShadow(QFrame.Raised)
def right(self, Form):
if not Form.objectName():
Form.setObjectName(u"Form")
Form.resize(500, 500)
self.rightgrip = QFrame(Form)
self.rightgrip.setObjectName(u"right")
self.rightgrip.setGeometry(QRect(0, 0, 10, 500))
self.rightgrip.setMinimumSize(QSize(10, 0))
self.rightgrip.setCursor(QCursor(Qt.SizeHorCursor))
self.rightgrip.setStyleSheet(u"background-color: rgb(255, 0, 127);")
self.rightgrip.setFrameShape(QFrame.NoFrame)
self.rightgrip.setFrameShadow(QFrame.Raised)
并实例化该类为四个边框,作为窗口边缘:
# 实例化四个CustomGrip对象,作为窗口边缘
self.left_grip = CustomGrip(self, Qt.LeftEdge, True)
self.right_grip = CustomGrip(self, Qt.RightEdge, True)
self.top_grip = CustomGrip(self, Qt.TopEdge, True)
self.bottom_grip = CustomGrip(self, Qt.BottomEdge, True)
还需要根据窗口状态更新四个窗口边缘对象的位置和大小,具体使用见完整代码。
5、完整代码
项目结构:
images:UI界面资源文件
modules:
app_functions.py:软件功能具体程序
custon_grips.py:自定义组件类
resources_rc.py:qrc的py文件
ui_functions.py:UI功能具体程序
ui_main.py:ui的py文件
本示例将主窗口的入口程序放到了main.py,将UI界面功能的程序放到了ui_functions.py,通过子类unctions继承父类MyWindow,来实现代码分离:
main.py:
from PySide6.QtCore import Qt, QPoint
from PySide6.QtWidgets import QApplication, QMainWindow, QButtonGroup
from modules import *
class MyWindow(QMainWindow):
def __init__(self):
super().__init__()
self.ui = Ui_MainWindow()
global widget
widget = self.ui
self.ui.setupUi(self)
# 设置UI功能
# ===============================================
UIFunctions.ui_definitions(self)
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton and self.ui.top_bar.geometry().contains(event.position().toPoint()):
self.old_pos = event.globalPosition().toPoint()
def mouseMoveEvent(self, event):
if self.old_pos is not None:
delta = QPoint(event.globalPosition().toPoint() - self.old_pos)
self.move(self.x() + delta.x(), self.y() + delta.y())
self.old_pos = event.globalPosition().toPoint()
def mouseReleaseEvent(self, event):
self.old_pos = None
def resizeEvent(self, event):
UIFunctions.resize_grips(self)
if __name__ == '__main__':
app = QApplication([])
window = MyWindow()
window.show()
app.exec()
ui_functions.py:
from PySide6.QtCore import Qt, QTimer, QEvent
from .custom_grips import CustomGrip
from main import MyWindow
GLOBAL_STATE = False
GLOBAL_TITLE_BAR = True
class UIFunctions(MyWindow):
# 最大化/还原
def maximize_restore(self):
global GLOBAL_STATE
status = GLOBAL_STATE
if status == False:
self.showMaximized()
GLOBAL_STATE = True
self.left_grip.hide()
self.right_grip.hide()
self.top_grip.hide()
self.bottom_grip.hide()
else:
GLOBAL_STATE = False
self.showNormal()
self.resize(self.width() + 1, self.height() + 1)
self.left_grip.show()
self.right_grip.show()
self.top_grip.show()
self.bottom_grip.show()
def resize_grips(self):
self.left_grip.setGeometry(0, 10, 10, self.height())
self.right_grip.setGeometry(self.width() - 10, 10, 10, self.height())
self.top_grip.setGeometry(0, 0, self.width(), 10)
self.bottom_grip.setGeometry(0, self.height() - 10, self.width(), 10)
def ui_definitions(self):
def double_click_max(event):
# 双击切换最大化
if event.type() == QEvent.MouseButtonDblClick:
QTimer.singleShot(250, lambda: UIFunctions.maximize_restore(self))
self.ui.top_bar.mouseDoubleClickEvent = double_click_max
# 实例化四个CustomGrip对象,作为窗口边缘
self.left_grip = CustomGrip(self, Qt.LeftEdge, True)
self.right_grip = CustomGrip(self, Qt.RightEdge, True)
self.top_grip = CustomGrip(self, Qt.TopEdge, True)
self.bottom_grip = CustomGrip(self, Qt.BottomEdge, True)
# 最大化
self.ui.btn_max.clicked.connect(lambda: UIFunctions.maximize_restore(self))
# 隐藏标题栏
self.setWindowFlags(Qt.WindowType.FramelessWindowHint)
self.setAttribute(Qt.WA_TranslucentBackground)
# 最小化
self.ui.btn_min.clicked.connect(self.showMinimized)
# 关闭
self.ui.btn_close.clicked.connect(self.close)
版权归原作者 布呐呐na 所有, 如有侵权,请联系我们删除。