PyQt5实现无边框窗口的标题拖动和窗口缩放
网上找了半天都找不到好用的PyQt5无边框窗口的实现,借鉴部分前辈的窗口拖放代码,自己实现了一下无边框窗口,问题可能还有一点,慢慢改吧
先做个笔记
py文件
#!/usr/bin/envpython #-*-coding:utf-8-*- fromPyQt5.QtWidgetsimportQWidget,QLabel,QPushButton,QVBoxLayout fromPyQt5.QtCoreimportQt,QPoint fromPyQt5.QtGuiimportQFont,QCursor classQTitleLabel(QLabel): """ 新建标题栏标签类 """ def__init__(self,*args): super(QTitleLabel,self).__init__(*args) self.setAlignment(Qt.AlignLeft|Qt.AlignVCenter) self.setFixedHeight(30) classQTitleButton(QPushButton): """ 新建标题栏按钮类 """ def__init__(self,*args): super(QTitleButton,self).__init__(*args) self.setFont(QFont("Webdings"))#特殊字体以不借助图片实现最小化最大化和关闭按钮 self.setFixedWidth(40) classQUnFrameWindow(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()#设置鼠标跟踪判断默认值 definitDrag(self): #设置鼠标跟踪判断扳机默认值 self._move_drag=False self._corner_drag=False self._bottom_drag=False self._right_drag=False definitTitleLabel(self): #安放标题栏标签 self._TitleLabel=QTitleLabel(self) self._TitleLabel.setMouseTracking(True)#设置标题栏标签鼠标跟踪(如不设,则标题栏内在widget上层,无法实现跟踪) self._TitleLabel.setIndent(10)#设置标题栏文本缩进 self._TitleLabel.move(0,0)#标题栏安放到左上角 definitLayout(self): #设置框架布局 self._MainLayout=QVBoxLayout() self._MainLayout.setSpacing(0) self._MainLayout.addWidget(QLabel(),Qt.AlignLeft)#顶一个QLabel在竖放框架第一行,以免正常内容挤占到标题范围里 self._MainLayout.addStretch() self.setLayout(self._MainLayout) defaddLayout(self,QLayout): #给widget定义一个addLayout函数,以实现往竖放框架的正确内容区内嵌套Layout框架 self._MainLayout.addLayout(QLayout) def_setTitleText(self,func): #设置标题栏标签的装饰器函数 defwrapper(*args): self._TitleLabel.setText(*args) returnfunc(*args) returnwrapper defsetTitleAlignment(self,alignment): #给widget定义一个setTitleAlignment函数,以实现标题栏标签的对齐方式设定 self._TitleLabel.setAlignment(alignment|Qt.AlignVCenter) defsetCloseButton(self,bool): #给widget定义一个setCloseButton函数,为True时设置一个关闭按钮 ifbool==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)#按钮信号连接到关闭窗口的槽函数 defsetMinMaxButtons(self,bool): #给widget定义一个setMinMaxButtons函数,为True时设置一组最小化最大化按钮 ifbool==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 defresizeEvent(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)forxinrange(self.width()-self._padding,self.width()+1) foryinrange(1,self.height()-self._padding)] self._bottom_rect=[QPoint(x,y)forxinrange(1,self.width()-self._padding) foryinrange(self.height()-self._padding,self.height()+1)] self._corner_rect=[QPoint(x,y)forxinrange(self.width()-self._padding,self.width()+1) foryinrange(self.height()-self._padding,self.height()+1)] defmousePressEvent(self,event): #重写鼠标点击的事件 if(event.button()==Qt.LeftButton)and(event.pos()inself._corner_rect): #鼠标左键点击右下角边界区域 self._corner_drag=True event.accept() elif(event.button()==Qt.LeftButton)and(event.pos()inself._right_rect): #鼠标左键点击右侧边界区域 self._right_drag=True event.accept() elif(event.button()==Qt.LeftButton)and(event.pos()inself._bottom_rect): #鼠标左键点击下侧边界区域 self._bottom_drag=True event.accept() elif(event.button()==Qt.LeftButton)and(event.y()qss文件
/**********Title**********/ QTitleLabel{ background-color:Gainsboro; font:10010pt; } /**********Button**********/ QTitleButton{ background-color:rgba(255,255,255,0); color:black; border:0px; font:10010pt; } QTitleButton#MinMaxButton:hover{ background-color:#D0D0D1; border:0px; font:10010pt; } QTitleButton#CloseButton:hover{ background-color:#D32424; color:white; border:0px; font:10010pt; }以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。