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;
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。