温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

PyQt5如何实现无边框窗口的标题拖动和窗口缩放

发布时间:2021-06-28 10:32:33 来源:亿速云 阅读:539 作者:小新 栏目:开发技术

这篇文章主要为大家展示了“PyQt5如何实现无边框窗口的标题拖动和窗口缩放”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“PyQt5如何实现无边框窗口的标题拖动和窗口缩放”这篇文章吧。

py文件

#!/usr/bin/env python #-*- coding:utf-8 -*- from PyQt5.QtWidgets import QWidget, QLabel, QPushButton, QVBoxLayout from PyQt5.QtCore import Qt, QPoint from PyQt5.QtGui import QFont, QCursor class QTitleLabel(QLabel):   """   新建标题栏标签类   """   def __init__(self, *args):     super(QTitleLabel, self).__init__(*args)     self.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)     self.setFixedHeight(30) class QTitleButton(QPushButton):   """   新建标题栏按钮类   """   def __init__(self, *args):     super(QTitleButton, self).__init__(*args)     self.setFont(QFont("Webdings")) # 特殊字体以不借助图片实现最小化最大化和关闭按钮     self.setFixedWidth(40) class QUnFrameWindow(QWidget):   """   无边框窗口类   """   def __init__(self):     super(QUnFrameWindow, self).__init__(None, Qt.FramelessWindowHint) # 设置为顶级窗口,无边框     self._padding = 5 # 设置边界宽度为5     self.initTitleLabel() # 安放标题栏标签     self.setWindowTitle = self._setTitleText(self.setWindowTitle) # 用装饰器将设置WindowTitle名字函数共享到标题栏标签上     self.setWindowTitle("UnFrameWindow")     self.initLayout() # 设置框架布局     self.setMinimumWidth(250)     self.setMouseTracking(True) # 设置widget鼠标跟踪     self.initDrag() # 设置鼠标跟踪判断默认值   def initDrag(self):     # 设置鼠标跟踪判断扳机默认值     self._move_drag = False     self._corner_drag = False     self._bottom_drag = False     self._right_drag = False   def initTitleLabel(self):     # 安放标题栏标签     self._TitleLabel = QTitleLabel(self)     self._TitleLabel.setMouseTracking(True) # 设置标题栏标签鼠标跟踪(如不设,则标题栏内在widget上层,无法实现跟踪)     self._TitleLabel.setIndent(10) # 设置标题栏文本缩进     self._TitleLabel.move(0, 0) # 标题栏安放到左上角   def initLayout(self):     # 设置框架布局     self._MainLayout = QVBoxLayout()     self._MainLayout.setSpacing(0)     self._MainLayout.addWidget(QLabel(), Qt.AlignLeft) # 顶一个QLabel在竖放框架第一行,以免正常内容挤占到标题范围里     self._MainLayout.addStretch()     self.setLayout(self._MainLayout)   def addLayout(self, QLayout):     # 给widget定义一个addLayout函数,以实现往竖放框架的正确内容区内嵌套Layout框架     self._MainLayout.addLayout(QLayout)   def _setTitleText(self, func):     # 设置标题栏标签的装饰器函数     def wrapper(*args):       self._TitleLabel.setText(*args)       return func(*args)     return wrapper   def setTitleAlignment(self, alignment):     # 给widget定义一个setTitleAlignment函数,以实现标题栏标签的对齐方式设定     self._TitleLabel.setAlignment(alignment | Qt.AlignVCenter)   def setCloseButton(self, bool):     # 给widget定义一个setCloseButton函数,为True时设置一个关闭按钮     if bool == True:       self._CloseButton = QTitleButton(b'\xef\x81\xb2'.decode("utf-8"), self)       self._CloseButton.setObjectName("CloseButton") # 设置按钮的ObjectName以在qss样式表内定义不同的按钮样式       self._CloseButton.setToolTip("关闭窗口")       self._CloseButton.setMouseTracking(True) # 设置按钮鼠标跟踪(如不设,则按钮在widget上层,无法实现跟踪)       self._CloseButton.setFixedHeight(self._TitleLabel.height()) # 设置按钮高度为标题栏高度       self._CloseButton.clicked.connect(self.close) # 按钮信号连接到关闭窗口的槽函数   def setMinMaxButtons(self, bool):     # 给widget定义一个setMinMaxButtons函数,为True时设置一组最小化最大化按钮     if bool == True:       self._MinimumButton = QTitleButton(b'\xef\x80\xb0'.decode("utf-8"), self)       self._MinimumButton.setObjectName("MinMaxButton") # 设置按钮的ObjectName以在qss样式表内定义不同的按钮样式       self._MinimumButton.setToolTip("最小化")       self._MinimumButton.setMouseTracking(True) # 设置按钮鼠标跟踪(如不设,则按钮在widget上层,无法实现跟踪)       self._MinimumButton.setFixedHeight(self._TitleLabel.height()) # 设置按钮高度为标题栏高度       self._MinimumButton.clicked.connect(self.showMinimized) # 按钮信号连接到最小化窗口的槽函数       self._MaximumButton = QTitleButton(b'\xef\x80\xb1'.decode("utf-8"), self)       self._MaximumButton.setObjectName("MinMaxButton") # 设置按钮的ObjectName以在qss样式表内定义不同的按钮样式       self._MaximumButton.setToolTip("最大化")       self._MaximumButton.setMouseTracking(True) # 设置按钮鼠标跟踪(如不设,则按钮在widget上层,无法实现跟踪)       self._MaximumButton.setFixedHeight(self._TitleLabel.height()) # 设置按钮高度为标题栏高度       self._MaximumButton.clicked.connect(self._changeNormalButton) # 按钮信号连接切换到恢复窗口大小按钮函数   def _changeNormalButton(self):     # 切换到恢复窗口大小按钮     try:       self.showMaximized() # 先实现窗口最大化       self._MaximumButton.setText(b'\xef\x80\xb2'.decode("utf-8")) # 更改按钮文本       self._MaximumButton.setToolTip("恢复") # 更改按钮提示       self._MaximumButton.disconnect() # 断开原本的信号槽连接       self._MaximumButton.clicked.connect(self._changeMaxButton) # 重新连接信号和槽     except:       pass   def _changeMaxButton(self):     # 切换到最大化按钮     try:       self.showNormal()       self._MaximumButton.setText(b'\xef\x80\xb1'.decode("utf-8"))       self._MaximumButton.setToolTip("最大化")       self._MaximumButton.disconnect()       self._MaximumButton.clicked.connect(self._changeNormalButton)     except:       pass   def resizeEvent(self, QResizeEvent):     # 自定义窗口调整大小事件     self._TitleLabel.setFixedWidth(self.width()) # 将标题标签始终设为窗口宽度     # 分别移动三个按钮到正确的位置     try:       self._CloseButton.move(self.width() - self._CloseButton.width(), 0)     except:       pass     try:       self._MinimumButton.move(self.width() - (self._CloseButton.width() + 1) * 3 + 1, 0)     except:       pass     try:       self._MaximumButton.move(self.width() - (self._CloseButton.width() + 1) * 2 + 1, 0)     except:       pass     # 重新调整边界范围以备实现鼠标拖放缩放窗口大小,采用三个列表生成式生成三个列表     self._right_rect = [QPoint(x, y) for x in range(self.width() - self._padding, self.width() + 1)               for y in range(1, self.height() - self._padding)]     self._bottom_rect = [QPoint(x, y) for x in range(1, self.width() - self._padding)              for y in range(self.height() - self._padding, self.height() + 1)]     self._corner_rect = [QPoint(x, y) for x in range(self.width() - self._padding, self.width() + 1)                   for y in range(self.height() - self._padding, self.height() + 1)]   def mousePressEvent(self, event):     # 重写鼠标点击的事件     if (event.button() == Qt.LeftButton) and (event.pos() in self._corner_rect):       # 鼠标左键点击右下角边界区域       self._corner_drag = True       event.accept()     elif (event.button() == Qt.LeftButton) and (event.pos() in self._right_rect):       # 鼠标左键点击右侧边界区域       self._right_drag = True       event.accept()     elif (event.button() == Qt.LeftButton) and (event.pos() in self._bottom_rect):       # 鼠标左键点击下侧边界区域       self._bottom_drag = True       event.accept()     elif (event.button() == Qt.LeftButton) and (event.y() < self._TitleLabel.height()):       # 鼠标左键点击标题栏区域       self._move_drag = True       self.move_DragPosition = event.globalPos() - self.pos()       event.accept()   def mouseMoveEvent(self, QMouseEvent):     # 判断鼠标位置切换鼠标手势     if QMouseEvent.pos() in self._corner_rect:       self.setCursor(Qt.SizeFDiagCursor)     elif QMouseEvent.pos() in self._bottom_rect:       self.setCursor(Qt.SizeVerCursor)     elif QMouseEvent.pos() in self._right_rect:       self.setCursor(Qt.SizeHorCursor)     else:       self.setCursor(Qt.ArrowCursor)     # 当鼠标左键点击不放及满足点击区域的要求后,分别实现不同的窗口调整     # 没有定义左方和上方相关的5个方向,主要是因为实现起来不难,但是效果很差,拖放的时候窗口闪烁,再研究研究是否有更好的实现     if Qt.LeftButton and self._right_drag:       # 右侧调整窗口宽度       self.resize(QMouseEvent.pos().x(), self.height())       QMouseEvent.accept()     elif Qt.LeftButton and self._bottom_drag:       # 下侧调整窗口高度       self.resize(self.width(), QMouseEvent.pos().y())       QMouseEvent.accept()     elif Qt.LeftButton and self._corner_drag:       # 右下角同时调整高度和宽度       self.resize(QMouseEvent.pos().x(), QMouseEvent.pos().y())       QMouseEvent.accept()     elif Qt.LeftButton and self._move_drag:       # 标题栏拖放窗口位置       self.move(QMouseEvent.globalPos() - self.move_DragPosition)       QMouseEvent.accept()   def mouseReleaseEvent(self, QMouseEvent):     # 鼠标释放后,各扳机复位     self._move_drag = False     self._corner_drag = False     self._bottom_drag = False     self._right_drag = False if __name__ == "__main__":   from PyQt5.QtWidgets import QApplication   import sys   app = QApplication(sys.argv)   app.setStyleSheet(open("./UnFrameStyle.qss").read())   window = QUnFrameWindow()   window.setCloseButton(True)   window.setMinMaxButtons(True)   window.show()   sys.exit(app.exec_())

qss文件

/**********Title**********/ QTitleLabel{     background-color: Gainsboro;     font: 100 10pt; } /**********Button**********/ QTitleButton{     background-color: rgba(255, 255, 255, 0);     color: black;     border: 0px;     font: 100 10pt; } QTitleButton#MinMaxButton:hover{     background-color: #D0D0D1;     border: 0px;     font: 100 10pt; } QTitleButton#CloseButton:hover{     background-color: #D32424;     color: white;     border: 0px;     font: 100 10pt; }

以上是“PyQt5如何实现无边框窗口的标题拖动和窗口缩放”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI