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


文章目录

  • 【最终版】PyQt5 自定义标题栏,实现无边框,最小化最大化关闭事件,窗口拖动移动,窗口改变大小,仿百度网盘色调美化,添加内容窗口
    • 前言
    • 1.文件架构【新增】
    • 2.实现效果【增加】
    • 3. 标题栏Qtdesigner的ui设计(ui设计代码)
    • 4. 设置标题和图标【改】
    • 5.最大化最小化关闭事件
    • 6.窗口拖动移动,窗口改变大小
    • 7.增加内容窗口事件【新增】
    • 8.仿百度网盘色调QSS美化【改】
    • 9.完整标题栏逻辑代码 CallTitletest.py【改】
    • 10.增添内容窗口控件测试【新增】

前言

此篇文章是在【PyQt5 自定义标题栏,实现无边框,最小化最大化关闭事件,窗口拖动移动,窗口改变大小,仿百度网盘色调美化】这篇文章的基础上改进的。

下面文章内容如果没有说明,就是和基础版的一样。如果说了【改】或【新增】就说明和基础版的不一致了。


1.文件架构【新增】


|

|-TitleTest.py 标题栏ui代码

|

|-CallTitleTest.py 标题栏逻辑代码

|- - - - -|

|-------- |-textedit_test.py内容窗口ui代码

|---------|-Call_textedit_test.py内容窗口逻辑代码


2.实现效果【增加】

没有内容的标题栏效果

在标题栏加入内容后效果

标题栏适应了内容窗口大小。


3. 标题栏Qtdesigner的ui设计(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"))

4. 设置标题和图标【改】

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

单独设置一个函数来整理【标题和图标】设置,如果全部放在__init__初始化函数里,会很混乱的。只需在__init__中初始化这个函数即可。

改:把设置无边框部分放在QSS美化部分讲。这部分就说【标题和图标】的设置函数。

如果看来基础版的代码,可以发现,我把无边框和【标题和图标】分成两个函数了。因为【标题和图标】设置部分做了改变。

首先在__init__函数中设置两个参数来接收图标和标题

# 接收图标和标题
self.icon_path = icon_path
self.title = title
    def icon_and_title(self):########在测试时记得设置自己的图标地址self.label.setAlignment(Qt.AlignCenter)self.label_2.setStyleSheet('''font-family:"方正胖娃_GBK";font-size:11px;''')if self.icon_path:# 设置图标self.pix = QPixmap(self.icon_path)  # 注意修改Windows路径问题self.label.setPixmap(self.pix)self.label.setScaledContents(True)else:self.label.setStyleSheet('''font-family:"Webdings";font-size:13px;color:blue;''')self.label.setText('~')if self.title:# 设置标题self.label_2.setText(self.title)else:# 设置标题self.label_2.setText('我的APP')

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

因为可能出现不想输入标题和图标的情况,所以为其设置了默认值。其中图标是使用了webdings特殊字体。

Webdings是特殊字体,想了解请看文章:PyQt5 使用 webdings,Wingdings 字体来替代某些常用图标

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


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

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

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

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 字体来替代某些常用图片

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

__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坐标


7.增加内容窗口事件【新增】

单单设计标题栏是没有用的,只有在标题栏放置了内容控件才能实现目的。

在本程序设计中是把内容控件放置在widget_2上,通过在widget_2上设置垂直布局,然后通过addwidget新增控件。

为了更加灵活,把标题栏设置得适应传进来的内容控件的大小。随其大小变化。通过resize()函数实现调整大小

初始化__init__函数部分代码

if widget_2_sub:self.widget_2_sub = widget_2_subself.resize(self.widget_2_sub.width(), self.widget_2_sub.height() + self.widget.height())self.insert_widget()

首先判断是否有传进内容控件,如果没有,就不进行【界面大小】和【内容控件增添函数】了。

self.insert_widget()内容控件增添函数

def insert_widget(self):# widget_2控件初始化与创建垂直布局QVBoxLayoutself.widget_2_vcroLayout = QVBoxLayout(self.widget_2)self.widget_2_vcroLayout.setContentsMargins(0, 0, 0, 0)  # 设置布局外部大小self.widget_2_vcroLayout.setSpacing(0)  # 设置布局控件间距self.widget_2_vcroLayout.setObjectName("widget_2_vcroLayout")  # 设置Object属性名称,QSS可以用到# 设置垂直布局对齐方式self.widget_2_vcroLayout.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignTop)self.widget_2.setLayout(self.widget_2_vcroLayout)  # 这一步暂时没有发现有什么用,self.widget_2_vcroLayout.addWidget(self.widget_2_sub)  # 增添内容控件

.


8.仿百度网盘色调QSS美化【改】

如果没有美化,效果如下图

可以看到,效果很不理想。还是要进行一定美化才好看。

【1】设置无边框

def _init_main_window(self):# 设置窗体无边框self.setWindowFlags(Qt.FramelessWindowHint)# 设置背景透明self.setAttribute(Qt.WA_TranslucentBackground)

【2】设置背景和按钮颜色

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

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

.

my_Qss()函数

def my_Qss(self):# 给标题栏控件设置别的属性名,这样就不会在美化时和新加进来的内容栏窗口的控件有冲突了self.widget.setProperty('other_name', 'title_bar_widget')self.widget_2.setProperty('other_name', 'title_bar_widget_2')self.label.setProperty('other_name', 'title_bar_lable')self.label_2.setProperty('other_name', 'title_bar_lable_2')self.pushButton.setProperty('other_name', 'title_bar_pushButton')self.pushButton_2.setProperty('other_name', 'title_bar_pushButton_2')self.pushButton_3.setProperty('other_name', 'title_bar_pushButton_3')# Qss美化qssStyle = '''QWidget[other_name='title_bar_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[other_name='title_bar_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;}QPushButton[other_name='title_bar_pushButton']{font-family:"Webdings";text-align:top;background:#6DDF6D;border-radius:5px;border:none;font-size:13px;}QPushButton[other_name='title_bar_pushButton']:hover{background:green;}QPushButton[other_name='title_bar_pushButton_2']{font-family:"Webdings";background:#F7D674;border-radius:5px;border:none;font-size:13px;}QPushButton[other_name='title_bar_pushButton_2']:hover{background:yellow;}QPushButton[other_name='title_bar_pushButton_3']{font-family:"Webdings";background:#F76677;border-radius:5px;border:none;font-size:13px;}QPushButton[other_name='title_bar_pushButton_3']:hover{background:red;}'''self.setStyleSheet(qssStyle)

在选择器上改变了, # 给标题栏控件设置别的属性名,这样就不会在美化时和新加进来的内容栏窗口的控件有冲突了。

如果不这样做,就会和新加进来的内容控件相冲突了。

注:只是参考使用了【百度网盘】的颜色,并不是和其一样。


9.完整标题栏逻辑代码 CallTitletest.py【改】

CallTitletest.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# author:mgboy time:2020/8/5
import sysfrom PyQt5.QtCore import pyqtSlot, Qt, QPoint
from PyQt5.QtGui import QFont, QEnterEvent, QPixmap
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QDialog, QVBoxLayout, QPushButton
from PyQt5 import QtCore, QtWidgetsfrom TitleTest import Ui_Formclass TitleWindow(QWidget, Ui_Form):def __init__(self, widget_2_sub=None, icon_path=None, title=None, parent=None):super(TitleWindow, self).__init__(parent)self.setupUi(self)self._init_main_window()  # 主窗口初始化设置# 接收图标和标题self.icon_path = icon_pathself.title = titleself.icon_and_title()  # 设置图标与标题self._initDrag()  # 设置鼠标跟踪判断扳机默认值self.setMouseTracking(True)  # 设置widget鼠标跟踪self._close_max_min_icon()  # 设置 3 个按钮的图标字体self.my_Qss()  # 美化self.widget.installEventFilter(self)  # 初始化事件过滤器self.widget_2.installEventFilter(self)if widget_2_sub:self.widget_2_sub = widget_2_subself.resize(self.widget_2_sub.width(), self.widget_2_sub.height() + self.widget.height())self.insert_widget()def insert_widget(self):# widget_2控件初始化与创建垂直布局QVBoxLayoutself.widget_2_vcroLayout = QVBoxLayout(self.widget_2)self.widget_2_vcroLayout.setContentsMargins(0, 0, 0, 0)  # 设置布局外部大小self.widget_2_vcroLayout.setSpacing(0)  # 设置布局控件间距self.widget_2_vcroLayout.setObjectName("widget_2_vcroLayout")  # 设置Object属性名称,QSS可以用到# 设置垂直布局对齐方式self.widget_2_vcroLayout.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignTop)self.widget_2.setLayout(self.widget_2_vcroLayout)  # 这一步暂时没有发现有什么用,self.widget_2_vcroLayout.addWidget(self.widget_2_sub)  # 增添内容控件def _init_main_window(self):# 设置窗体无边框self.setWindowFlags(Qt.FramelessWindowHint)# 设置背景透明self.setAttribute(Qt.WA_TranslucentBackground)def icon_and_title(self):########在测试时记得设置自己的图标地址self.label.setAlignment(Qt.AlignCenter)self.label_2.setStyleSheet('''font-family:"方正胖娃_GBK";font-size:11px;''')if self.icon_path:# 设置图标self.pix = QPixmap(self.icon_path)  # 注意修改Windows路径问题self.label.setPixmap(self.pix)self.label.setScaledContents(True)else:self.label.setStyleSheet('''font-family:"Webdings";font-size:13px;color:blue;''')self.label.setText('~')if self.title:# 设置标题self.label_2.setText(self.title)else:# 设置标题self.label_2.setText('我的APP')def _initDrag(self):# 设置鼠标跟踪判断扳机默认值self._move_drag = Falseself._corner_drag = Falseself._bottom_drag = Falseself._right_drag = Falsedef _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 eventFilter(self, obj, event):# 事件过滤器,用于解决鼠标进入其它控件后还原为标准鼠标样式if isinstance(event, QEnterEvent):self.setCursor(Qt.ArrowCursor)return super(TitleWindow, 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):# 给标题栏控件设置别的属性名,这样就不会在美化时和新加进来的内容栏窗口的控件有冲突了self.widget.setProperty('other_name', 'title_bar_widget')self.widget_2.setProperty('other_name', 'title_bar_widget_2')self.label.setProperty('other_name', 'title_bar_lable')self.label_2.setProperty('other_name', 'title_bar_lable_2')self.pushButton.setProperty('other_name', 'title_bar_pushButton')self.pushButton_2.setProperty('other_name', 'title_bar_pushButton_2')self.pushButton_3.setProperty('other_name', 'title_bar_pushButton_3')# Qss美化qssStyle = '''QWidget[other_name='title_bar_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[other_name='title_bar_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;}QPushButton[other_name='title_bar_pushButton']{font-family:"Webdings";text-align:top;background:#6DDF6D;border-radius:5px;border:none;font-size:13px;}QPushButton[other_name='title_bar_pushButton']:hover{background:green;}QPushButton[other_name='title_bar_pushButton_2']{font-family:"Webdings";background:#F7D674;border-radius:5px;border:none;font-size:13px;}QPushButton[other_name='title_bar_pushButton_2']:hover{background:yellow;}QPushButton[other_name='title_bar_pushButton_3']{font-family:"Webdings";background:#F76677;border-radius:5px;border:none;font-size:13px;}QPushButton[other_name='title_bar_pushButton_3']:hover{background:red;}'''self.setStyleSheet(qssStyle)if __name__ == "__main__":# 适配2k等高分辨率屏幕,低分辨率屏幕可以缺省QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)app = QApplication(sys.argv)myWin = TitleWindow()myWin.show()sys.exit(app.exec_())

.


10.增添内容窗口控件测试【新增】

首先,用designer设置一个widget控件窗口,然后在其逻辑代码中引用标题栏的TitleWindow类,把内容窗口传进去即可,还可以传进图标地址和标题。

from CallTitleTest import TitleWindow
if __name__ == "__main__":#适配2k等高分辨率屏幕QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)app = QApplication(sys.argv)myWin = TitleWindow(widget_2_sub=MyWindow(),icon_path=None,title='OmyG')myWin.show()sys.exit(app.exec_())

注意第5行的引用方法,不要和其他程序混淆了

是将内容窗口MyWindow()类直接进去的。

注意如果想传图标,注意路径写法。

【1】内容窗口ui代码

textedit_test.py

from PyQt5 import QtCore, QtGui, QtWidgetsclass Ui_Form(object):def setupUi(self, Form):Form.setObjectName("Form")Form.resize(320, 240)self.verticalLayout = QtWidgets.QVBoxLayout(Form)self.verticalLayout.setObjectName("verticalLayout")self.horizontalLayout = QtWidgets.QHBoxLayout()self.horizontalLayout.setObjectName("horizontalLayout")self.lineEdit = QtWidgets.QLineEdit(Form)self.lineEdit.setObjectName("lineEdit")self.horizontalLayout.addWidget(self.lineEdit)self.pushButton = QtWidgets.QPushButton(Form)self.pushButton.setObjectName("pushButton")self.horizontalLayout.addWidget(self.pushButton)self.verticalLayout.addLayout(self.horizontalLayout)self.textEdit = QtWidgets.QTextEdit(Form)self.textEdit.setObjectName("textEdit")self.verticalLayout.addWidget(self.textEdit)self.retranslateUi(Form)QtCore.QMetaObject.connectSlotsByName(Form)def retranslateUi(self, Form):_translate = QtCore.QCoreApplication.translateForm.setWindowTitle(_translate("Form", "Form"))self.pushButton.setText(_translate("Form", "确定"))

.

【2】内容窗口逻辑代码

Call_textedit_test.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# author:mgboy time:2020/7/26
import sysfrom PyQt5.QtWidgets import QApplication, QMainWindow,QWidget,QDialog
from PyQt5 import QtCorefrom textedit_test import Ui_Form
from CallTitleTest import TitleWindowclass MyWindow(QWidget, Ui_Form):def __init__(self, parent=None):super(MyWindow, self).__init__(parent)self.setupUi(self)self.pushButton.clicked.connect(self.show_text)self.lineEdit.returnPressed.connect(self.show_text)self.lineEdit.setPlaceholderText('请输入字符串')self.lineEdit.setClearButtonEnabled(True)qss = '''QPushButton#pushButton{width:30px;height:15px;border-radius:5px;background-color:gray;}'''self.setStyleSheet(qss)def show_text(self):text = '输入了:' + self.lineEdit.text()self.textEdit.insertPlainText(text)def returnPressed_func(self):current_text = self.lineEdit.text()print("文本框回车键信号", current_text)self.textBrowser.append("文本框回车键信号" + current_text + '\n'+ '\n' + '回车键')if __name__ == "__main__":#适配2k等高分辨率屏幕QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)app = QApplication(sys.argv)myWin = TitleWindow(widget_2_sub=MyWindow(),icon_path=None,title='OmyG')myWin.show()sys.exit(app.exec_())

.

四个代码文件放在同目录下。

直接运行Call_textedit_test.py文件即可

不是运行标题栏文件了。因为是通过from CallTitleTest import TitleWindow引用标题栏文件的。

.

.

.

.

【最终版】PyQt5 自定义标题栏,实现无边框,最小化最大化关闭事件,窗口拖动移动,窗口改变大小,仿百度网盘色调美化,添加内容窗口相关推荐

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

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

  2. PyQt5下界面设计, 无边框加阴影界面, 鼠标左键移动事件

    本人小白, 网罗各个网页与资源学习总结的内容, 设置界面无边框且留有阴影, 且鼠标左键可以拖动界面的方法. 首先我们寻找一个模板进行学习演示, 例如腾讯会议的界面: 本人会仿照这个界面进行演示说明, ...

  3. Qt实战案例(42)——利用Qt实现自定义标题栏功能(自定义最大化、最小化、关闭等功能)

    目录 一.项目介绍(为什么要自自定义标题栏功能) 二.项目基本配置 三.UI界面设计 四.主程序实现 4.1 隐藏边框 4.2 设置最大化(还原),最小化,关闭按钮的样式风格 4.3 关闭按钮的实现 ...

  4. android百度网盘倍速,百度网盘在线倍数播放-全网最强,已做群组视频适配,不用保存文件也可倍速,无vip限制(附加安卓倍速版)...

    // ==UserScript== // @name 百度网盘在线倍数播放-全网最强,已做群组视频适配,不用保存文件也可倍速,无vip限制(附加安卓倍速版) // @namespace http:// ...

  5. [转]仿163网盘无刷新文件上传系统

    原文链接:http://www.cnblogs.com/cloudgamer/archive/2008/10/20/1314766.html 这个仿163网盘无刷新文件上传系统,并没有用使用.net的 ...

  6. 百度网盘Linux版本能用吗,百度网盘Linux版使用体验效果

    以下是百度网盘Linux版使用体验效果分享,它可以在LinuxMint 19.1操作系统中运行. 前言 百度推出了重量级Linux软件,即百度网盘Linux版,这是一款百度推出的官方Linux客户端, ...

  7. 互联网晚报 | 12月30日 星期四 | 百度网盘青春版正式上线;汽车之家回应“年底大裁员”;A股年内成交额创历史新高...

    ‍ 今日看点 ✦ 腾讯微信支付支持全量商家小程序场景开通银联云闪付功能 ✦ 百度网盘青春版正式上线:免费空间10GB,支持无差别速率下载 ✦ 汽车之家:不存在大规模裁员,整体人员优化幅度不及5% ✦ ...

  8. MAC版Proxyee Down百度网盘高速下载器教程

    MAC版Proxyee Down百度网盘高速下载器教程 1. 介绍 2. 下载 3. 软件安装 4. 使用SwitchyOmega接管代理 1. 安装 2. 配置 SwitchyOmega 5. 创建 ...

  9. 仿163网盘无刷新多文件上传系统

    这个仿163网盘无刷新多文件上传系统,并没有用使用.net的控件,完全的手工制作.前台基本上是静态的,跟后台没有关系,所以后台用什么语言做都可以(后面有各个版本的实例下载). 本来觉得这个系统会很复杂 ...

最新文章

  1. 写代码如坐禅:你是哪一类程序员?
  2. mysql 支持 pdo_使php支持pdo_mysql_睿合科技
  3. 洛谷——P1067 多项式输出
  4. 从初创型到独角兽企业,监控架构演进的那些事儿
  5. 使用注解装配Bean
  6. 循序渐进的敏捷-每日例会
  7. CreateaJointCurve.txt
  8. VXLAN详解(一)
  9. Matlab之深度学习工作流程
  10. Python的print输出对齐
  11. 智能网联车载终端渗透率提升之道
  12. 自动生成注释作者名字和日期等信息(IDEA Java类)
  13. 500台机以上大型网吧设计方案(转)
  14. Linux就这个范儿 第14章 身在江湖
  15. appstore上传截图的各种尺寸
  16. ARM官方汇编与ARM GNU汇编中的伪操作
  17. 李刚疯狂java抄袭,推荐:疯狂java讲义--李刚著作(3)
  18. axure生成的html不能用360浏览器打开
  19. BZOJ 1941: [Sdoi2010]Hide and Seek KDtree + 估价函数
  20. 美国新法案为金融机构制定勒索软件防御和响应指南

热门文章

  1. 20200525【建设银行】建信金融科技实习生笔试卷L
  2. Python爬虫实战 下载原力创付费文档---全屏阅览式
  3. Android IBinder的linkToDeath介绍及情景模拟
  4. 致传统企业码友的一封信:不够痛就别微服务
  5. 三星Samsung SL-K3300NR 驱动
  6. 【解决方案】SkeyeVSS助力智能考场视频监控,为高考保驾护航
  7. 利安德巴塞尔公司最新分子回收中试车间正式投运
  8. python中uniform randint_Python 随机数函数(random,uniform,randint,randrange,shuffle,sample)...
  9. SketchUp:SketchUp草图大师软件使用技巧总结(视图操作,绘图环境优化,缩放/镜像/对齐/桌边倒圆角案例)
  10. 利用iSpring Free上传PPt课件并上传至Moodle教学平台