1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > PyQt5 自定义标题栏 实现无边框 最小化最大化关闭事件 窗口拖动移动 窗口改变大

PyQt5 自定义标题栏 实现无边框 最小化最大化关闭事件 窗口拖动移动 窗口改变大

时间:2019-08-08 16:20:44

相关推荐

PyQt5 自定义标题栏 实现无边框 最小化最大化关闭事件 窗口拖动移动 窗口改变大

PyQt5 自定义标题栏,实现无边框,最小化最大化关闭事件,窗口拖动移动,窗口改变大小,仿百度网盘色调美化

文章目录

PyQt5 自定义标题栏,实现无边框,最小化最大化关闭事件,窗口拖动移动,窗口改变大小,仿百度网盘色调美化1.实现效果2. Qtdesigner设计(ui设计代码)3. 设置无边框,标题和图标4.最大化最小化关闭事件5.窗口拖动移动,窗口改变大小6.仿百度网盘色调QSS美化7.完整逻辑代码 CallTitleTest.py

1.实现效果

文件框架

|

|-TitleTest.pyui代码

|

|-CallTitleTest.py逻辑代码

|

2. Qtdesigner设计(ui设计代码)

设计图:

布局

具体控件设置请看 ui的py文件

请留意 3 个pushButton和 2 个lable的大小设计

TitleTest.py

# -*- coding: utf-8 -*-# Form implementation generated from reading ui file 'TitleTest.ui'## Created by: PyQt5 UI code generator 5.13.0## WARNING! All changes made in this file will be lost!from PyQt5 import QtCore, QtGui, QtWidgetsclass Ui_Form(object):def setupUi(self, Form):Form.setObjectName("Form")Form.resize(648, 432)self.verticalLayout = QtWidgets.QVBoxLayout(Form)self.verticalLayout.setContentsMargins(0, 0, 0, 0)self.verticalLayout.setSpacing(0)self.verticalLayout.setObjectName("verticalLayout")self.widget = QtWidgets.QWidget(Form)self.widget.setMaximumSize(QtCore.QSize(16777215, 35))self.widget.setObjectName("widget")self.horizontalLayout = QtWidgets.QHBoxLayout(self.widget)self.horizontalLayout.setContentsMargins(0, 0, 0, 0)self.horizontalLayout.setSpacing(0)self.horizontalLayout.setObjectName("horizontalLayout")spacerItem = QtWidgets.QSpacerItem(5, 20, QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Minimum)self.horizontalLayout.addItem(spacerItem)self.label = QtWidgets.QLabel(self.widget)sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)sizePolicy.setHorizontalStretch(20)sizePolicy.setVerticalStretch(20)sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth())self.label.setSizePolicy(sizePolicy)self.label.setMaximumSize(QtCore.QSize(20, 20))self.label.setObjectName("label")self.horizontalLayout.addWidget(self.label)spacerItem1 = QtWidgets.QSpacerItem(5, 20, QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Minimum)self.horizontalLayout.addItem(spacerItem1)self.label_2 = QtWidgets.QLabel(self.widget)sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)sizePolicy.setHorizontalStretch(0)sizePolicy.setVerticalStretch(30)sizePolicy.setHeightForWidth(self.label_2.sizePolicy().hasHeightForWidth())self.label_2.setSizePolicy(sizePolicy)self.label_2.setObjectName("label_2")self.horizontalLayout.addWidget(self.label_2)spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)self.horizontalLayout.addItem(spacerItem2)self.pushButton = QtWidgets.QPushButton(self.widget)sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)sizePolicy.setHorizontalStretch(20)sizePolicy.setVerticalStretch(20)sizePolicy.setHeightForWidth(self.pushButton.sizePolicy().hasHeightForWidth())self.pushButton.setSizePolicy(sizePolicy)self.pushButton.setMinimumSize(QtCore.QSize(0, 0))self.pushButton.setMaximumSize(QtCore.QSize(20, 20))self.pushButton.setObjectName("pushButton")self.horizontalLayout.addWidget(self.pushButton)spacerItem3 = QtWidgets.QSpacerItem(8, 20, QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Minimum)self.horizontalLayout.addItem(spacerItem3)self.pushButton_2 = QtWidgets.QPushButton(self.widget)sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)sizePolicy.setHorizontalStretch(20)sizePolicy.setVerticalStretch(20)sizePolicy.setHeightForWidth(self.pushButton_2.sizePolicy().hasHeightForWidth())self.pushButton_2.setSizePolicy(sizePolicy)self.pushButton_2.setMaximumSize(QtCore.QSize(20, 20))self.pushButton_2.setObjectName("pushButton_2")self.horizontalLayout.addWidget(self.pushButton_2)spacerItem4 = QtWidgets.QSpacerItem(8, 20, QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Minimum)self.horizontalLayout.addItem(spacerItem4)self.pushButton_3 = QtWidgets.QPushButton(self.widget)sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)sizePolicy.setHorizontalStretch(20)sizePolicy.setVerticalStretch(20)sizePolicy.setHeightForWidth(self.pushButton_3.sizePolicy().hasHeightForWidth())self.pushButton_3.setSizePolicy(sizePolicy)self.pushButton_3.setMaximumSize(QtCore.QSize(20, 20))self.pushButton_3.setObjectName("pushButton_3")self.horizontalLayout.addWidget(self.pushButton_3)spacerItem5 = QtWidgets.QSpacerItem(5, 20, QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Minimum)self.horizontalLayout.addItem(spacerItem5)self.verticalLayout.addWidget(self.widget)self.widget_2 = QtWidgets.QWidget(Form)self.widget_2.setObjectName("widget_2")self.verticalLayout.addWidget(self.widget_2)self.retranslateUi(Form)QtCore.QMetaObject.connectSlotsByName(Form)def retranslateUi(self, Form):_translate = QtCore.QCoreApplication.translateForm.setWindowTitle(_translate("Form", "Form"))self.label.setText(_translate("Form", "图标"))self.label_2.setText(_translate("Form", "TextLabel"))self.pushButton.setToolTip(_translate("Form", "<html><head/><body><p>最小化</p></body></html>"))self.pushButton.setText(_translate("Form", "-"))self.pushButton_2.setToolTip(_translate("Form", "<html><head/><body><p>最大化</p></body></html>"))self.pushButton_2.setText(_translate("Form", "O"))self.pushButton_3.setToolTip(_translate("Form", "<html><head/><body><p>关闭</p></body></html>"))self.pushButton_3.setText(_translate("Form", "X"))

3. 设置无边框,标题和图标

完整的逻辑代码请看最下面的CallTitleTest.py文件代码

单独设置一个函数来整理无边框,标题和图标设置_init_main_window,如果全部放在__init__初始化函数里,会很混乱的

def _init_main_window(self):# 设置窗体无边框self.setWindowFlags(Qt.FramelessWindowHint)# 设置背景透明self.setAttribute(Qt.WA_TranslucentBackground)########在测试时记得设置自己的图标地址# 设置图标w = self.label.width()h = self.label.height()self.pix = QPixmap(r"D:\code_python\CalPx_test\images\481ee7d90dfcc5c5418eaa8bf94370f2_cr.jpg") # 注意修改Windows路径问题self.label.setPixmap(self.pix)self.label.setScaledContents(True)# 设置标题self.label_2.setText('我的APP')# 设置标题字体,大小self.label_2.setStyleSheet('''font-family:"方正胖娃_GBK";font-size:11px;''')

########在测试时记得设置自己的图标地址

我是用两个 QLable 标签控件来放置图标和标题的,用QSS进行一定美化

进行读写文件时,在字符串前加 r,u,b,f 的含义

要在__init__初始化函数里初始化函数

self. _init_main_window()

4.最大化最小化关闭事件

最大化最小化关闭事件是通过三个按钮来实现

编写三个按钮的信号与槽函数

def _close_max_min_icon(self):self.pushButton_3.setText('r')self.pushButton_2.setText('1')self.pushButton.setText('0')@pyqtSlot()def on_pushButton_clicked(self):# 最小化self.showMinimized()@pyqtSlot()def on_pushButton_2_clicked(self):# 最大化与复原if self.isMaximized():self.showNormal()self.pushButton_2.setText('1') # 切换放大按钮图标字体self.pushButton_2.setToolTip("<html><head/><body><p>最大化</p></body></html>")else:self.showMaximized()self.pushButton_2.setText('2')self.pushButton_2.setToolTip("<html><head/><body><p>恢复</p></body></html>")@pyqtSlot()def on_pushButton_3_clicked(self):# 关闭程序self.close()

def _close_max_min_icon(self):函数不是按钮的信号与槽函数,在这里说是因为它是设置三个按钮的图标关键字,使用了webdings字体,需要在__init__初始化

PyQt5 使用 webdings,Wingdings 字体来替代某些常用图片

5.窗口拖动移动,窗口改变大小

__init__初始化函数里声明代码并初始化一些函数

self._initDrag() # 设置鼠标跟踪判断扳机默认值self.setMouseTracking(True) # 设置widget鼠标跟踪self.widget.installEventFilter(self) # 初始化事件过滤器self.widget_2.installEventFilter(self)

事件过滤器函数

def eventFilter(self, obj, event):# 事件过滤器,用于解决鼠标进入其它控件后还原为标准鼠标样式if isinstance(event, QEnterEvent):self.setCursor(Qt.ArrowCursor)return super(MyWindow, self).eventFilter(obj, event) # 注意 ,MyWindow是所在类的名称# return QWidget.eventFilter(self, obj, event) # 用这个也行,但要注意修改窗口类型

因为设置了主窗口透明化,所以要专门用这个过滤器来恢复鼠标形状,两个子窗口widgetwidget_2都要经过这个过滤器

鼠标事件

def resizeEvent(self, QResizeEvent):# 自定义窗口调整大小事件# 改变窗口大小的三个坐标范围self._right_rect = [QPoint(x, y) for x in range(self.width() - 5, self.width() + 5)for y in range(self.widget.height() + 20, self.height() - 5)]self._bottom_rect = [QPoint(x, y) for x in range(1, self.width() - 5)for y in range(self.height() - 5, self.height() + 1)]self._corner_rect = [QPoint(x, y) for x in range(self.width() - 5, self.width() + 1)for y in range(self.height() - 5, self.height() + 1)]def mousePressEvent(self, event):# 重写鼠标点击的事件if (event.button() == Qt.LeftButton) and (event.pos() in self._corner_rect):# 鼠标左键点击右下角边界区域self._corner_drag = Trueevent.accept()elif (event.button() == Qt.LeftButton) and (event.pos() in self._right_rect):# 鼠标左键点击右侧边界区域self._right_drag = Trueevent.accept()elif (event.button() == Qt.LeftButton) and (event.pos() in self._bottom_rect):# 鼠标左键点击下侧边界区域self._bottom_drag = Trueevent.accept()elif (event.button() == Qt.LeftButton) and (event.y() < self.widget.height()):# 鼠标左键点击标题栏区域self._move_drag = Trueself.move_DragPosition = event.globalPos() - self.pos()event.accept()def mouseMoveEvent(self, QMouseEvent):# 判断鼠标位置切换鼠标手势if QMouseEvent.pos() in self._corner_rect: # QMouseEvent.pos()获取相对位置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)# 当鼠标左键点击不放及满足点击区域的要求后,分别实现不同的窗口调整# 没有定义左方和上方相关的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 = Falseself._corner_drag = Falseself._bottom_drag = Falseself._right_drag = False

def resizeEvent(self, QResizeEvent)通过这个函数获取改变大小的坐标范围,只有鼠标处于这个范围,就可以改变程序窗口大小。

我只设置了三个方向可以改变窗口大小,其他的可以自行修改。

坐标问题:

self.width()获取主窗口的宽,self.height()获取主窗口的高

相对应的self.widget.width()是获取子窗口widget的宽

event.pos()QMouseEvent.pos()获取相对于软件窗口的像素坐标

event.globalPos()QMouseEvent.globalPos()获取相对于屏幕的像素坐标

后面的x,y分别是其的x坐标和y坐标

6.仿百度网盘色调QSS美化

设置背景色

百度网盘程序的标题栏的颜色便灰,内容窗口便白色,使用屏幕拾色器获取具体颜色编码。

两款屏幕取色拾色器(免安装,1MB左右大小)

QSS代码

QWidget#widget{background-color:#eef0f6;border-left:0.5px solid lightgray;border-right:0.5px solid lightgray;border-top:0.5px solid lightgray;border-bottom:0.5px solid #e5e5e5;border-top-left-radius: 5px;border-top-right-radius: 5px;}QWidget#widget_2{background-color:#ffffff;border-left:0.5px solid lightgray;border-right:0.5px solid lightgray;border-bottom:0.5px solid #e5e5e5;border-bottom-left-radius: 5px;border-bottom-right-radius: 5px;padding:5px 5px 5px 5px}

美化三个按钮

QSS代码

QPushButton#pushButton{font-family:"Webdings";text-align:top;background:#6DDF6D;border-radius:5px;border:none;font-size:13px;}QPushButton#pushButton:hover{background:green;}QPushButton#pushButton_2{font-family:"Webdings";background:#F7D674;border-radius:5px;border:none;font-size:13px;}QPushButton#pushButton_2:hover{background:yellow;}QPushButton#pushButton_3{font-family:"Webdings";background:#F76677;border-radius:5px;border:none;font-size:13px;}QPushButton#pushButton_3:hover{background:red;}

7.完整逻辑代码 CallTitleTest.py

CallTitleTest.py

#!/usr/bin/env python# -*- coding: utf-8 -*-# author:mgboy time:/8/5import sysfrom PyQt5.QtCore import pyqtSlot, Qt, QPointfrom PyQt5.QtGui import QFont, QEnterEvent, QPixmapfrom PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QDialogfrom PyQt5 import QtCorefrom TitleTest import Ui_Formclass MyWindow(QWidget, Ui_Form):def __init__(self, parent=None):super(MyWindow, self).__init__(parent)self.setupUi(self)self._init_main_window() # 主窗口初始化设置self._initDrag() # 设置鼠标跟踪判断扳机默认值self.setMouseTracking(True) # 设置widget鼠标跟踪self._close_max_min_icon() # 设置 3 个按钮的图标字体print(self.width(),self.height())self.my_Qss() # 美化self.widget.installEventFilter(self) # 初始化事件过滤器self.widget_2.installEventFilter(self)def _init_main_window(self):# 设置窗体无边框self.setWindowFlags(Qt.FramelessWindowHint)# 设置背景透明self.setAttribute(Qt.WA_TranslucentBackground)########在测试时记得设置自己的图标地址# 设置图标w = self.label.width()h = self.label.height()self.pix = QPixmap(r"D:\code_python\CalPx_test\images\481ee7d90dfcc5c5418eaa8bf94370f2_cr.jpg") # 注意修改Windows路径问题self.label.setPixmap(self.pix)self.label.setScaledContents(True)# 设置标题self.label_2.setText('我的APP')# 设置标题字体,大小self.label_2.setStyleSheet('''font-family:"方正胖娃_GBK";font-size:11px;''')def _initDrag(self):# 设置鼠标跟踪判断扳机默认值self._move_drag = Falseself._corner_drag = Falseself._bottom_drag = Falseself._right_drag = Falsedef _close_max_min_icon(self):# 设置按钮图标使用webdings特殊字体self.pushButton_3.setText('r')self.pushButton_2.setText('1')self.pushButton.setText('0')@pyqtSlot()def on_pushButton_clicked(self):# 最小化self.showMinimized()@pyqtSlot()def on_pushButton_2_clicked(self):# 最大化与复原if self.isMaximized():self.showNormal()self.pushButton_2.setText('1') # 切换放大按钮图标self.pushButton_2.setToolTip("<html><head/><body><p>最大化</p></body></html>")else:self.showMaximized()self.pushButton_2.setText('2')self.pushButton_2.setToolTip("<html><head/><body><p>恢复</p></body></html>")@pyqtSlot()def on_pushButton_3_clicked(self):# 关闭程序self.close()def eventFilter(self, obj, event):# 事件过滤器,用于解决鼠标进入其它控件后还原为标准鼠标样式if isinstance(event, QEnterEvent):self.setCursor(Qt.ArrowCursor)return super(MyWindow, self).eventFilter(obj, event) # 注意 ,MyWindow是所在类的名称# return QWidget.eventFilter(self, obj, event) # 用这个也行,但要注意修改窗口类型def resizeEvent(self, QResizeEvent):# 自定义窗口调整大小事件# 改变窗口大小的三个坐标范围self._right_rect = [QPoint(x, y) for x in range(self.width() - 5, self.width() + 5)for y in range(self.widget.height() + 20, self.height() - 5)]self._bottom_rect = [QPoint(x, y) for x in range(1, self.width() - 5)for y in range(self.height() - 5, self.height() + 1)]self._corner_rect = [QPoint(x, y) for x in range(self.width() - 5, self.width() + 1)for y in range(self.height() - 5, self.height() + 1)]def mousePressEvent(self, event):# 重写鼠标点击的事件if (event.button() == Qt.LeftButton) and (event.pos() in self._corner_rect):# 鼠标左键点击右下角边界区域self._corner_drag = Trueevent.accept()elif (event.button() == Qt.LeftButton) and (event.pos() in self._right_rect):# 鼠标左键点击右侧边界区域self._right_drag = Trueevent.accept()elif (event.button() == Qt.LeftButton) and (event.pos() in self._bottom_rect):# 鼠标左键点击下侧边界区域self._bottom_drag = Trueevent.accept()elif (event.button() == Qt.LeftButton) and (event.y() < self.widget.height()):# 鼠标左键点击标题栏区域self._move_drag = Trueself.move_DragPosition = event.globalPos() - self.pos()event.accept()def mouseMoveEvent(self, QMouseEvent):# 判断鼠标位置切换鼠标手势if QMouseEvent.pos() in self._corner_rect: # QMouseEvent.pos()获取相对位置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)# 当鼠标左键点击不放及满足点击区域的要求后,分别实现不同的窗口调整# 没有定义左方和上方相关的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 = Falseself._corner_drag = Falseself._bottom_drag = Falseself._right_drag = Falsedef my_Qss(self):# Qss美化qssStyle = '''QWidget#widget{background-color:#eef0f6;border-left:0.5px solid lightgray;border-right:0.5px solid lightgray;border-top:0.5px solid lightgray;border-bottom:0.5px solid #e5e5e5;border-top-left-radius: 5px;border-top-right-radius: 5px;}QWidget#widget_2{background-color:#ffffff;border-left:0.5px solid lightgray;border-right:0.5px solid lightgray;border-bottom:0.5px solid #e5e5e5;border-bottom-left-radius: 5px;border-bottom-right-radius: 5px;padding:5px 5px 5px 5px}QPushButton#pushButton{font-family:"Webdings";text-align:top;background:#6DDF6D;border-radius:5px;border:none;font-size:13px;}QPushButton#pushButton:hover{background:green;}QPushButton#pushButton_2{font-family:"Webdings";background:#F7D674;border-radius:5px;border:none;font-size:13px;}QPushButton#pushButton_2:hover{background:yellow;}QPushButton#pushButton_3{font-family:"Webdings";background:#F76677;border-radius:5px;border:none;font-size:13px;}QPushButton#pushButton_3:hover{background:red;}'''self.setStyleSheet(qssStyle)if __name__ == "__main__":# 适配2k等高分辨率屏幕,低分辨率屏幕可以缺省QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)app = QApplication(sys.argv)myWin = MyWindow()myWin.show()sys.exit(app.exec_())

.

要加入其它控件,可以先使用designer设计一个QWidget类窗口,再加入widget_2子窗口即可。最近会写一下怎么加。设计时要注意widget_2子窗口的大小是648*397,最好按照这个大小再来设计。也可以把标题类设置为一个接口文件,调用即可,不过这要修改逻辑代码。

.

.

.

.

PyQt5 自定义标题栏 实现无边框 最小化最大化关闭事件 窗口拖动移动 窗口改变大小 仿百度网盘色调美化

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。