目录

  • 1、参考:
  • 2、创建窗口:
  • 2.1、一般方式创建窗口
  • 2.2、面向对象思想创建窗口
  • 3、控件
  • 3.1、按钮:
  • 3.2、输入
  • 3.3、展示控件(标签)
  • 3.4、容器控件
  • 3.5、结构控件
  • 3.6、滚动控件QAbstractScrollArea
  • 3.7、辅助控件
  • 3.8、其他
  • 4、QObject
  • 4.1、继承关系
  • 4.2、对象名称、属性
  • 4.2.1、qss样式
  • 4.3、设定/查找 父子对象
  • 5、信号与槽机制
  • 5.1、侦听释放对象:obj.destroyed.connect()、删除对象deleteLater()
  • 5.1.1、侦听释放对象:obj.destroyed.connect()
  • 5.1.2、删除对象deleteLater()
  • 5.2、侦听对象名称改变:objectNameChanged()
  • 5.3、侦听鼠标点击事件:clicked()
  • 5.4、侦听窗口标题变化:windowTitleChanged()
  • 5.4、判断是否是控件类型isWidgetType()、判断是否(直接或间接)继承自某个父类inherits()
  • 5.5、事件处理机制


1、参考:

模块名

作用

QtWidgets

包含一整套UI元素控件,用于建立符合系统风格的界面(例如窗口最小化最大化关闭按钮根据在window还是mac的窗口 自适应地在右上角或左上角)

QtGui

包含多种基本图形功能的类(字体、图形、图表、颜色等)

QtCore

包含了包的核心的非GUI功能(时间、目录、数据类型、文本流、连接、线程进程等)

QtWebKit、QtTest

QtMultimedia、QtMultimediaWidgets

多媒体

Qt

将基本全部模块中的类综合到一个单一的模块中

2、创建窗口:

2.1、一般方式创建窗口

from PyQt5.Qt import *
import sys

app = QApplication(sys.argv)  # 将命令行传进来的参数传递给app
print(app.arguments())        # 上一行传递的sys.argv可以通过app.arguments()获得
# 打印:['C:\\Users\\ZHUIAO\\PycharmProjects\\pythonProject\\main.py']

print(qApp.arguments())         # 全局的应用程序对象,打印内容和上面 app.arguments()一样


window = QWidget()
window.setWindowTitle("这是标题")  # 标题
window.resize(300, 100)  # 窗口宽300,高100
window.move(400, 200)  # 窗口距离左侧400,距离上方200

label = QLabel(window)
label.setText("这是label")
label.move(120, 40)

window.show()  # 显示窗口

# sys.exit(0)表示正常退出,若程序运行错误,app.exec_()返回非0
# app.exec_()表示让整个程序进入主循环,不要停止
sys.exit(app.exec_())

pyqt QLable setStyleSheet 字体 pyqt字体颜色_初始化

如果没有指定父控件(父控件如下面的QLabel(window)),那么它本身就作为了顶层控件(窗口)
系统会自动给窗口添加一些装饰(如标题栏,最大化最小化)
对比上面代码和下面代码,label没有父控件,可以label.show()显示为第二个窗口,而且也有自己的标题栏、最大化最小化按关闭钮

from PyQt5.Qt import *
import sys

app = QApplication(sys.argv)  # 将命令行传进来的参数传递给app

window = QWidget(); window.setWindowTitle("这是标题"); window.resize(300, 100); window.move(400, 200)
window.show()

label = QLabel()
label.setText("这是label")
label.move(120, 40)

label.show()  # 显示窗口

# sys.exit(0)表示正常退出,若程序运行错误,app.exec_()返回非0
# app.exec_()表示让整个程序进入主循环,不要停止
sys.exit(app.exec_())

pyqt QLable setStyleSheet 字体 pyqt字体颜色_python_02

2.2、面向对象思想创建窗口

from PyQt5.Qt import *
import sys


class Window(QWidget):
    def __init__(self):
        super().__init__()  # 在初始化QWidget时会进行一些操作,所以在继承QWidget时必须先执行父类初始化函数
        self.setWindowTitle("这是窗口标题")
        self.resize(300, 80)
        self.setup_ui()

    def setup_ui(self):
        label = QLabel(self)
        label.setText("这是标签")


app = QApplication(sys.argv)

window = Window()
window.show()

sys.exit(app.exec_())

pyqt QLable setStyleSheet 字体 pyqt字体颜色_python_03

3、控件

3.1、按钮:

名称

说明

QPushButton

普通按钮

QCommandLinkButton

可以显示详情

QRadioButton

单选按钮(选单个)

QCheckBox

复选按钮(同时选多个)

from PyQt5.Qt import *
import sys


class Window(QWidget):
    def __init__(self):
        super().__init__()  # 在初始化QWidget时会进行一些操作,所以在继承QWidget时必须先执行父类初始化函数
        self.setWindowTitle("这是窗口标题")
        self.resize(300, 100)
        self.setup_ui()

    def setup_ui(self):
        # 创建一个垂直布局,所有组件加到这个布局中
        vbox_all = QVBoxLayout()

        # QPushButton =======================================================
        btn1 = QPushButton(self)
        btn1.setText("btn1 QPushButton")
        btn1.clicked.connect(lambda: self.btnFun("点击QPushButton按钮"))
        vbox_all.addWidget(btn1)        # btn1加入到vbox_all

        # QCommandLinkButton ======================================================
        btn2 = QCommandLinkButton(self)
        btn2.setText("btn2 QCommandLinkButton")
        btn2.setDescription("btn2按钮的描述")
        btn2.clicked.connect(lambda: self.btnFun("点击QCommandLinkButton按钮"))
        vbox_all.addWidget(btn2)        # btn2加入到vbox_all

        # QRadioButton ============================================================
        self.btn3_0 = QRadioButton("btn3 选项0")
        self.btn3_1 = QRadioButton("btn3 选项1")
        self.btn3_2 = QRadioButton("btn3 选项2")
        hbox3 = QHBoxLayout()
        hbox3.addWidget(self.btn3_0)
        hbox3.addWidget(self.btn3_1)
        hbox3.addWidget(self.btn3_2)
        self.btn3_0.toggled.connect(self.QRbtnFun)      # toggled:按钮状态更改就调用,选中和取消选中都会调用
        self.btn3_1.toggled.connect(self.QRbtnFun)
        self.btn3_2.toggled.connect(self.QRbtnFun)
        vbox_all.addLayout(hbox3)        # hbox3加入到vbox_all

        # QCheckBox ===============================================================
        self.btn4_0 = QCheckBox("btn4 选项0")
        self.btn4_1 = QCheckBox("btn4 选项1")
        hbox4 = QHBoxLayout()
        hbox4.addWidget(self.btn4_0)
        hbox4.addWidget(self.btn4_1)
        self.btn4_0.stateChanged.connect(self.QCbtnFun)
        self.btn4_1.stateChanged.connect(self.QCbtnFun)
        vbox_all.addLayout(hbox4)        # hbox4加入到vbox_all

        self.setLayout(vbox_all)

    def btnFun(self, message):
        print(message)

    def QRbtnFun(self):
        if self.btn3_0.isChecked():
            print("选中QRadioButton的选项0")
        elif self.btn3_1.isChecked():
            print("选中QRadioButton的选项1")
        else:
            print("选中QRadioButton的选项2")
    
    def QCbtnFun(self):
        if self.btn4_0.isChecked():
            print("选中QCheckBox的选项0")
        if self.btn4_1.isChecked():
            print("选中QCheckBox的选项1")


app = QApplication(sys.argv)

window = Window()
window.show()

sys.exit(app.exec_())

pyqt QLable setStyleSheet 字体 pyqt字体颜色_python_04

3.2、输入

  • 键盘输入

名称

说明

QLineEdit

单行输入

QTextEdit

多行输入(输入可以是超链接、图片等富文本)

QPlainTextEdit

普通的多行文本,将超链接、图片等富文本失效

QKeySequenceEdit

采集键盘输入,例如:Ctrl+A、Ctrl+C

from PyQt5.Qt import *
import sys


class Window(QWidget):
    def __init__(self):
        super().__init__()  # 在初始化QWidget时会进行一些操作,所以在继承QWidget时必须先执行父类初始化函数
        self.setWindowTitle("这是窗口标题")
        self.resize(300, 100)
        self.setup_ui()

    def setup_ui(self):
        # 创建一个垂直布局,所有组件加到这个布局中
        vbox_all = QVBoxLayout()

        # QLineEdit =======================================================
        self.edit1 = QLineEdit(self)
        self.edit1.setText("设置文本")
        print(f"获取文本:{self.edit1.text()}")
        self.edit1.setPlaceholderText("文本框为空时显示此文本!")
        self.edit1.setMaxLength(1000)        # 设置文本框最大字符数
        reg = QRegExp(".*")
        validator = QRegExpValidator(reg)
        self.edit1.setValidator(validator)        # 输入内容需要满足此正则表达式
        self.edit1.editingFinished.connect(lambda: self.lineFun("edit回车或文本编辑完成"))
        self.edit1.textChanged.connect(lambda: self.lineFun("edit文本变化"))
        vbox_all.addWidget(self.edit1)          # edit1 加入到vbox_all

        # QTextEdit ===================================================================
        self.edit2 = QTextEdit(self)
        self.edit2.setText("这是一个<a href='https://www.baidu.com/'>百度链接!</a>\n")      # 可接受HTML格式标签,点击不会自动跳转浏览器,但复制出来是带有链接
        # self.edit2.setPlainText("设置文本")       # 只接受纯文本(plain text),会覆盖上一行的setText
        # self.edit2.setHtml('<h1 style="color:red;">这是红色</h1>')        # 比setText更灵活,可插入涉及排版、样式、动画等元素
        print(f"获取文本:{self.edit2.toPlainText()}")
        self.edit2.setPlaceholderText("文本框为空时显示此文本!")
        self.edit2.textChanged.connect(self.TlineFun)
        vbox_all.addWidget(self.edit2)               # edit2加入到vbox_all

        self.setLayout(vbox_all)

    def lineFun(self, message):
        print(message)
        print(self.edit1.text())

    def TlineFun(self):
        print(self.edit2.toPlainText())


app = QApplication(sys.argv)

window = Window()
window.show()

sys.exit(app.exec_())

pyqt QLable setStyleSheet 字体 pyqt字体颜色_python_05

  • 步长调节(QAstractSpinBox)(键盘+鼠标)

名称

说明

QDateTimeEdit

采集时间,可以采集单独的日期和时间:

QDateEdit

QTimeEdit

QSpinBOX

采集一个整数

QDoubleSpinBox

采集浮点数

  • 下拉选项框:QComboBox、QFontComboBox(下拉选择字体)
  • 滑块(QAbstractSlider):

名称

说明

QDial

旋钮

QSlider

滑块

QScrollBar

滚动条

  • 橡皮筋选中:QRubberBand(可以用来选中控件)
  • 对话框(QDialog):

名称

说明

QColorDialog

选择颜色

QFileDialog

选择文件

QFondDialog

选择字体

QInputDialog

输入对话框

  • 日期:QCalendarWidget(选择日期)

3.3、展示控件(标签)

名称

说明

QLabel

展示标签,可以是普通文本、数字、富文本、图片、QLabel-动画(如gif)

QLCDNumber

LCD数字

QProgressBar

进度条

对话框(QDialog)

QMessageBox:展示警告、提示、错误

QErrorMessage:错误对话框

QProgressDialog:进度对话框

3.4、容器控件

名称

说明

QToolBox

一般容器

QDialogButtonBox

可以分多个组

QGroupBox

可以分多个组,每个组边框,有对应的标题

QMdiSubWindow

QMdiArea和QMdiSubWindow,可以在控件内创建控件,子控件有最大化最小化关闭按钮

3.5、结构控件

名称

说明

相关控件

QMainWindow

有菜单栏、工具栏、Dock Window、状态栏等

菜单栏QMenuBar(包含控件QMenu)、工具栏QToolBar(包含控件QToolButton)、状态栏QStatusBar

QTabWidget

标签控件

包含控件QTabBar

QStackedWidget

栈结构类型的控件,可以包含多个界面重复调用

QSplitter

可以将一个界面分割为多个界面

QDockWidget

可以将界面悬浮或停靠在父界面中

3.6、滚动控件QAbstractScrollArea

名称

说明

QTextBrowser

文本浏览器,可以滚动显示大篇幅的文本(和浏览.txt差不多)

QScrollArea

可以滚动浏览尺寸很大的图片,水平滚动和竖直滚动

QAbstractltemView

QColumnView分成多列浏览

QListView多行

QListView(包含QListWidget选择多列的元素、QUndoView撤销操作)

QTableView表格控件(包含控件QTableWidget)

QTreeWidget树形结构展开

QMdiarea

可以将多个子控件放里面??

QGraphicsView

画图

3.7、辅助控件

名称

说明

QFocusFrame

获取焦点,得到焦点的边框可以有不一样的样式显示

QSizeGrip

窗口右下角显示可以拖拉缩放窗口的小三角

QDesktopWidget

获取桌面信息,如尺寸、个数

3.8、其他

名称

说明

相关控件

向导、打印(QDialog)

QWizard,安装软件的向导

QWizardPage,软件安装向导中单独的一页

QAbstractPrintDialog,打印控件

QPrintDialog

QPrintPreviewDialog,打印前的预览界面

QPrintPreviewWidget

QPageSetupDialog,选择打印纸张大小方向等

欢迎界面QSplashScreen

QSplashScreen,打开软件加载时间长,可以先显示欢迎界面,例如打开Photoshop会先显示“PS 正在加载...”

功能性控件

QVideoWidget,在这个控件中播放视频

QCameraViewfinder(相机)

QWebEngineView,控件中打开打开网页

4、QObject

4.1、继承关系

  • 所有对象都是直接/间接继承自QObject类
  • 如果一个控件没有任何父控件,那么就会被当成顶层控件(窗口),多个顶层窗口相互独立
from PyQt5.Qt import *
import sys

app = QApplication(sys.argv)  # 将命令行传进来的参数传递给app

window1 = QWidget(); window1.setWindowTitle("窗口1"); window1.resize(250, 50); window1.move(400, 200)
window1.show() 
window2 = QWidget(); window2.setWindowTitle("窗口2"); window2.resize(250, 50); window2.move(650, 200)
window2.show() 

sys.exit(app.exec_())
  • 父对象被销毁时,子对象会自动被销毁。
from PyQt5.Qt import *
import sys

app = QApplication(sys.argv)  # 将命令行传进来的参数传递给app
window = QWidget(); window.setWindowTitle("这是标题"); window.resize(300, 150); window.move(400, 200)

obj0 = QObject()
obj1 = QObject()

# 监听obj1被释放
obj1.destroyed.connect(lambda: print("obj1被释放了"))
obj1.setParent(obj0)
del obj0            # 释放obj0对象时,自动释放obj1(实际上Python会自动回收未被引用的对象obj0)

window.show(); sys.exit(app.exec_())

# 输出
obj1被释放了
  • 子控件受父控件区域裁剪
from PyQt5.Qt import *
import sys

app = QApplication(sys.argv)  # 将命令行传进来的参数传递给app

window1 = QWidget(); window1.setWindowTitle("窗口1"); window1.resize(200, 200)
window1.setStyleSheet("background-color: red;")
window1.show()

window2 = QWidget(); window2.resize(400, 100)
window2.setStyleSheet("background-color: green;")
window2.setParent(window1)
window2.show() 

sys.exit(app.exec_())
  • 查看继承关系:mro()
mros = QObject.mro()
for mro in mros:
    print(mro)
    
# 输出:可以查看继承链
<class 'PyQt5.QtCore.QObject'>
<class 'sip.wrapper'>
<class 'sip.simplewrapper'>
<class 'object'>

4.2、对象名称、属性

函数

说明

setObjectName(“唯一名称”)

给Qt对象设置一个名称,而且一般是唯一的,当做对象的ID使用

objectName

获取Qt对象的名称

setProperty(“属性名称”, 值)

给一个Qt对象动态的添加一个属性与值

property(“属性名称”)

获取对象的属性值

dynamicPropertyNames()

获取对象中所有通过setProperty()设置的属性名称

obj = QObject()

obj.setObjectName("对象名称")   # 设置 对象obj 的名称
print(obj.objectName())         # 获取 对象obj 的名称,打印:对象名称

obj.setProperty("property_1", "value_1")        # 设置obj的属性与对应值(就是 obj对象 设置一组键值对)
obj.setProperty("property_2", "value_2")
print(obj.property("property_1"))               # 获取对应属性的值,打印:value_1

# 获取 所有属性的值
# 打印:[PyQt5.QtCore.QByteArray(b'property_1'), PyQt5.QtCore.QByteArray(b'property_2')]
print(obj.dynamicPropertyNames())

应用场景:

用于qss的ID选择器,属性选择器,方便统一设置样式
用于装饰器的信号与槽

4.2.1、qss样式

可以理解为css样式一样的作用,就是设置字体/按钮/标签等组件的大小颜色等样式。
例如:“font-size: 20px; color: red;”就是qss样式设置字体大小颜色。

  • 直接传qss样式的字符串:
from PyQt5.Qt import *
import sys

app = QApplication(sys.argv)  # 将命令行传进来的参数传递给app
window = QWidget(); window.setWindowTitle("这是标题"); window.resize(300, 100); window.move(400, 200)

label = QLabel(window)
label.setText("这是标签")
label.setStyleSheet("font-size: 20px; color: red;")     # 字体大小20像素,颜色红色

window.show()
sys.exit(app.exec_())

pyqt QLable setStyleSheet 字体 pyqt字体颜色_开发语言_06

  • 将qss样式放在另外一个文件,便于维护大量的样式

创建一个QObject.txt文件,将重命名为QObject.qss,用记事本打开,写入下面内容,就可以在匹配到QLabel组件时使用该样式。
还可以添加选择器

  • 例如下面选择将QLabel的字体大小设为20px红色
  • 还可以添加id选择器(将特定元件的id,也就是name,设置为特定的样式)
  • 也可以进一步用元件的属性值进行区分
QLabel {
    font-size: 10px;
    color: gray;
}
QLabel#id_1 {
    font-size: 20px;
    color: green;
}
QLabel#id_1[property_4="value_4"] {
    font-size: 30px;
    color: gray;
    border: 5px solid red;
    border-radius: 8px;
}
from PyQt5.Qt import *
import sys


app = QApplication(sys.argv)  # 将命令行传进来的参数传递给app
window = QWidget(); window.setWindowTitle("这是标题"); window.resize(300, 150); window.move(400, 200)

with open("QObject.qss", "r") as f:
    qApp.setStyleSheet(f.read())        # 下面组件的样式都会优先在这里匹配样式

label1 = QLabel(window)
label1.setText("这是标签1")

label2 = QLabel(window)
label2.setObjectName("id_1")    # 将标签的名称(id)设定为 id_1
label2.setText("这是标签2")
label2.move(30, 30)     # 标签移动 30, 30

label3 = QLabel(window)
label3.setObjectName("id_1")    # 将标签的名称(id)设定为 id_1
label3.setText("这是标签3")
label3.move(60, 60)


label4 = QLabel(window)
label4.setObjectName("id_1")    # 将标签的名称(id)设定为 id_1
label4.setProperty("property_4", "value_4")
label4.setText("这是标签4")
label4.move(90, 90)

window.show(); sys.exit(app.exec_())

pyqt QLable setStyleSheet 字体 pyqt字体颜色_初始化_07

4.3、设定/查找 父子对象

函数

说明

setParent(parent)

设置父对象

parent()

获取父对象

children()

获取所有直接子对象

findChild(参数1,参数2,参数3)

返回找到的第一个子对象:

参数1:指定类型/类型元组(如QPushButton, QLalbel)

参数2:名称(可省略)

参数3:查找选项(如Qt.FindChildrenRecursively递归查找还是其他,Qt.FindDirectChildrenOnly只查找直接子对象)

findChildren(参数1,参数2,参数3)

返回找到的所有子对象

from PyQt5.Qt import *
import sys

app = QApplication(sys.argv)  # 将命令行传进来的参数传递给app
window = QWidget(); window.setWindowTitle("这是标题"); window.resize(300, 150); window.move(400, 200)

obj0 = QObject()
obj0_0 = QObject()
obj0_1 = QObject()
obj0_0_0 = QObject()

obj0_0.setParent(obj0)
obj0_1.setParent(obj0)
obj0_0_0.setParent(obj0_0)

print("获取父对象:", obj0_0.parent())
print("获取所有直属的子对象:", obj0.children())

print("找到第一个子对象:", obj0.findChild(QObject))
print("找到所有子对象,包含间接子对象:", obj0.findChildren(QObject))

window.show(); sys.exit(app.exec_())

# 输出:
获取父对象: <PyQt5.QtCore.QObject object at 0x00000226BB66AD30>
获取所有直属的子对象: [<PyQt5.QtCore.QObject object at 0x00000226BB66ADC0>, <PyQt5.QtCore.QObject object at 0x00000226BB66AE50>]
找到第一个子对象: <PyQt5.QtCore.QObject object at 0x00000226BB66ADC0>
找到所有子对象,包含间接子对象: [<PyQt5.QtCore.QObject object at 0x00000226BB66ADC0>, <PyQt5.QtCore.QObject object at 0x00000226BB66AEE0>, <PyQt5.QtCore.QObject object at 0x00000226BB66AE50>]
  • 设置父对象时,如果子对象是可以显示的容器,那么父类也需要是容器,否则报错:
from PyQt5.Qt import *
import sys

app = QApplication(sys.argv)  # 将命令行传进来的参数传递给app
window = QWidget(); window.setWindowTitle("这是标题"); window.resize(300, 150); window.move(400, 200)

obj0 = QObject()
obj0_0 = QLabel()

obj0_0.setParent(obj0)      # 报错:label的父容器必须能显示的容器,而QObject不是容器

window.show(); sys.exit(app.exec_())

5、信号与槽机制

简单理解,信号就是侦听信号,槽就是接收到信号所需要执行的操作

  • 信号:内置信号(如QPushButton().pressed、QPushButton().clicked)、自定义信号(如pyqtSignal())。槽也有内置函数和自定义方法。一个信号可以连接多个槽函数或另外一个信号。一个槽可以监听多个信号。信号的参数可以是任何Python类型。
  • 连接方式:object.信号.connect(槽函数)。obj可以是控件 或 信号。

5.1、侦听释放对象:obj.destroyed.connect()、删除对象deleteLater()

5.1.1、侦听释放对象:obj.destroyed.connect()

  • destroyed()用法示例:
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)  # 将命令行传进来的参数传递给app
window = QWidget(); window.setWindowTitle("这是标题"); window.resize(300, 150); window.move(400, 200)

# connect():建立连接,监听obj1被释放
obj1 = QObject()
obj1.destroyed.connect(lambda: print("obj0被释放了"))
del obj1            # 释放obj0对象时,自动释放obj1(实际上Python会自动回收未被引用的对象obj0)


# destroyed():可以接受被释放的对象
obj2 = QObject()
def destroyedObj(myQObject):
    print("释放了对象:", myQObject)
obj2.destroyed.connect(destroyedObj)     # 监听obj2被释放
del obj2            # 释放obj2对象时,自动释放obj1(实际上Python会自动回收未被引用的对象obj0)

# disconnect():取消连接
obj3 = QObject()
obj3.destroyed.connect(lambda: print("obj3被释放了"))
obj3.destroyed.disconnect()     # 取消连接
del obj3            # 释放obj3对象时,会触发信号的发射(信号:obj3对象烧毁),但是断开连接后信号不会传递到槽函数

window.show(); sys.exit(app.exec_())

# 输出:
obj被释放了
释放了对象: <PyQt5.QtCore.QObject object at 0x000001E7CD5CF040>
  • 对象释放的先后顺序:
from PyQt5.Qt import *
import sys


class Window(QWidget):
    def __init__(self):
        super().__init__()  # 在初始化QWidget时会进行一些操作,所以在继承QWidget时必须先执行父类初始化函数
        self.setWindowTitle("这是窗口标题")
        self.resize(300, 80)
        self.setup_ui()

    def setup_ui(self):
        obj1 = QObject()
        obj2 = QObject()
        obj3 = QObject()

        obj3.setParent(obj2)    # obj3引用obj2
        obj2.setParent(obj1)    # obj2引用obj1,但是obj1没有被引用,所以会先释放obj1,然后obj2页没被引用而被释放,然后释放obj3

        obj1.destroyed.connect(lambda x:print(f"烧毁了obj1:{x}"))
        obj2.destroyed.connect(lambda x:print(f"烧毁了obj2:{x}"))
        obj3.destroyed.connect(lambda x:print(f"烧毁了obj3:{x}"))


app = QApplication(sys.argv)

window = Window()
window.show()

sys.exit(app.exec_())

理解:
例如先定义窗口window = QWidget();然后btn=QPushButton(window),这时候按钮对象btn是不会消失的,说明父组件window存在时子组件btn不会被烧毁,而如果定义btn_new=QPushButton(),那么按钮对象btn_new是不会出现的,因为没有父组件管理它了,方法结束后它就会自动烧毁了。(可以看下视频理解下)

  • del不是直接释放内存中的对象,实际上变量名obj指向内存中某个组件的地址,如果该组件被其他组件引用,del这个被引用的组件不会释放该组件内存,而是让变量名obj不指向该地址。如果有其他组件引用该组件就不会释放该组件:
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)  # 将命令行传进来的参数传递给app
window = QWidget(); window.setWindowTitle("这是标题"); window.resize(300, 150); window.move(400, 200)

obj1 = QLabel(window); obj1.setText("标题1")
obj1_temp = obj1        # 变量名 obj1和obj1_temp 都指向同一处内存地址
obj1.destroyed.connect(lambda x: print(f"烧毁了obj1:{x}"))
del obj1         # del obj1会删除obj1这个变量,但所指向的内存地址不会被释放(因为上面将obj1引用到window上:obj1 = QLabel(window))
print("obj1" in locals(), "obj1_temp" in locals())    # 只是 obj1 这个变量名被删除了
print(f"obj1没被烧毁:{obj1_temp}")  # 但是obj1或者obj1_temp所指向的内存空间并没有被删除


window.show(); sys.exit(app.exec_())

pyqt QLable setStyleSheet 字体 pyqt字体颜色_Qt_08

5.1.2、删除对象deleteLater()

  • 删除一个对象时,没有立即销毁对象,而是向主消息循环发送一个event,下一次主消息循环受到这个event之后才会销毁对象,这样做的好处是可以在这些延迟删除的时间内完成一些操作。
from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)  # 将命令行传进来的参数传递给app
window = QWidget(); window.setWindowTitle("这是标题"); window.resize(300, 150); window.move(400, 200)

obj1 = QLabel(window); obj1.setText("这是标题")
obj1.destroyed.connect(lambda x: print(f"烧毁了obj1:{x}"))
obj1.deleteLater()        # 不会立即删除obj1,会向主消息循环发生一个event,下一次循环收到这个event后再删除obj1
print(obj1)                 # obj1并没有立即删除,而是在下一次循环中被删除

window.show(); sys.exit(app.exec_())

pyqt QLable setStyleSheet 字体 pyqt字体颜色_控件_09

5.2、侦听对象名称改变:objectNameChanged()

from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)  # 将命令行传进来的参数传递给app
window = QWidget(); window.setWindowTitle("这是标题"); window.resize(300, 150); window.move(400, 200)


# objectNameChanged():侦听对象名称改变
obj = QObject()
def caoFun(myQObject):
    print("对象名称改变:", myQObject)
obj.objectNameChanged.connect(caoFun)     # 监听obj对象名称改变

obj.setObjectName("newName")

window.show(); sys.exit(app.exec_())

5.3、侦听鼠标点击事件:clicked()

from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)  # 将命令行传进来的参数传递给app
window = QWidget(); window.setWindowTitle("这是标题"); window.resize(300, 150); window.move(400, 200)

# disconnect():取消连接
btn = QPushButton(window)
btn.setText("点击我")
def caoFun():
    print("点击一次")
btn.clicked.connect(caoFun)

window.show(); sys.exit(app.exec_())

pyqt QLable setStyleSheet 字体 pyqt字体颜色_python_10

5.4、侦听窗口标题变化:windowTitleChanged()

from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)  # 将命令行传进来的参数传递给app
window = QWidget(); window.resize(300, 150); window.move(400, 200)

# windowTitleChanged():侦听窗口标题变化
def caoFun(title):
    print(f"输入的窗口名字:{title}")
    window.blockSignals(True)       # 临时暂停连接,类似于window.windowTitleChanged.disconnect()
    window.setWindowTitle(f"标题前缀---{title}")
    window.blockSignals(False)
window.windowTitleChanged.connect(caoFun)
window.setWindowTitle("设置标题1")

window.show(); sys.exit(app.exec_())

pyqt QLable setStyleSheet 字体 pyqt字体颜色_python_11

5.4、判断是否是控件类型isWidgetType()、判断是否(直接或间接)继承自某个父类inherits()

from PyQt5.Qt import *
import sys
app = QApplication(sys.argv)  # 将命令行传进来的参数传递给app
window = QWidget(); window.setWindowTitle("这是标题"); window.resize(300, 150); window.move(400, 200)

obj = QObject()
w = QWidget()
btn = QPushButton()
label = QLabel()

for o in [obj, w, btn, label]:
    # isWidgetType():判断是否是控件类型
    # inherits():判断是否(直接或间接)继承自某个父类
    print(o.isWidgetType(), o.inherits("QWidget"))

window.show(); sys.exit(app.exec_())

# 输出:注意w是QWidget对象,但是也可以看做是继承自QWidget,所以是True
False False
True True
True True
True True

5.5、事件处理机制

  • 事件处理:
  1. 点击事件被操作系统接收,分发给对应程序(PYQT5)
  2. 程序的消息循环不断检测事件队列是否有消息,当捕获到事件消息时,会包装成 “QEvent对象” ,并将“事件接受者QObject”和“事件对象QEvent”分发给 类QApplication() 的 函数notify(evt)中。
  3. 然后传送到组件(例如类QPushButton)的 event(evt)方法。
  4. 该方法根据evt的事件类型分发给对应的函数(例如mousePressEvent,mouseReleaseEvent,mouseClickEvent)
  • 我们可以重写 类QApplication(),并重写 函数notify() 来过滤事件:
from PyQt5.Qt import *
import sys

class App(QApplication):
    def notify(self, receiver, evt):      # QObject:事件的接受者,QEvent:被包装的事件对象

        # 过滤继承自QPushButton类的、鼠标按下的 事件
        if receiver.inherits("QPushButton") and evt.type() == QEvent.MouseButtonPress:
            print(receiver, evt)
        return super().notify(receiver, evt)      # 返回父类 notify()方法 的返回值

app = App(sys.argv)  # 将命令行传进来的参数传递给app
window = QWidget(); window.setWindowTitle("这是标题"); window.resize(300, 150); window.move(400, 200)

btn = QPushButton(window)
btn.setText("点击打印QPushButton的鼠标按下事件")
btn.move(50, 50)

window.show(); sys.exit(app.exec_())

pyqt QLable setStyleSheet 字体 pyqt字体颜色_控件_12

  • 例如针对特定事件,不进行 事件分发处理
from PyQt5.Qt import *
import sys

class App(QApplication):
    def notify(self, receiver, evt):      # QObject:事件的接受者,QEvent:被包装的事件对象

        # 过滤继承自QPushButton类的、鼠标按下的 事件
        if receiver.inherits("QPushButton") and evt.type() == QEvent.MouseButtonPress:
            print(receiver, evt)
        else:       # 只会将 上面事件就会分发事件
            return super().notify(receiver, evt)      # 返回父类 notify()方法 的返回值,也就是将事件分发下去

app = App(sys.argv)  # 将命令行传进来的参数传递给app
window = QWidget(); window.setWindowTitle("这是标题"); window.resize(300, 150); window.move(400, 200)

btn = QPushButton(window)
btn.setText("点击打印QPushButton的鼠标按下事件")
btn.move(50, 50)

window.show(); sys.exit(app.exec_())
  • 重写组件的event()方法:
from PyQt5.Qt import *
import sys

class Btn(QPushButton):
    def event(self, evt):
        if evt.type()==QEvent.MouseButtonPress:
            print("event函数\t鼠标点击事件:\t", evt)
        return super().event(evt)       # 调用父类方法

    def mousePressEvent(self, *args, **kwargs):
        print("鼠标被按下了")
        return super().mousePressEvent(*args, **kwargs)     # 这里就调用父函数,从而调用下面的btn.pressed.connect()函数

app = QApplication(sys.argv)  # 将命令行传进来的参数传递给app
window = QWidget(); window.setWindowTitle("这是标题"); window.resize(300, 150); window.move(400, 200)

btn = Btn(window)
btn.setText("点击打印QPushButton的鼠标按下事件")
btn.move(50, 50)

btn.pressed.connect(lambda:print("执行槽函数"))

window.show(); sys.exit(app.exec_())