Python Qt GUI与数据可视化编程(三)

2.4 自定义信号的使用

 

import sys
from PyQt5.QtCore import QObject,pyqtSlot,pyqtSignal

class Human(QObject):
    nameChanged = pyqtSignal(str)
    ##overload型信号有两种参数,一种是int,一种是str
    ageChanged = pyqtSignal([int],[str])

    def __init__(self,name='Mike',age=10,parent=None):
        super().__init__(parent)
        self.setAge(age)
        self.setName(name)

    def setAge(self,age):
        self.__age = age  #这句话是干嘛的
        self.ageChanged.emit(self.__age) #发射int参数信号
        if age<=18:
            ageInfo = "你是少年"
        elif(18

运行结果;

Python Qt GUI与数据可视化编程(三)_第1张图片

Python Qt GUI与数据可视化编程(三)_第2张图片

①信号定义

一般信号: 信号变量名 = pyqtSignal(信号的参数类型)    ##信号会将这个参数发射给槽函数

                   eg:nameChanged = pyqtSignal(int)

overload型信号:信号变量名 = pyqtSignal([信号参数类型1],[信号参数类型2])

ageChanged = pyqtSignal([int],[str])

②信号发射

一般信号:信号变量名.emit(信号的参数)

self.nameChanged.emit(self.__name)

overload型信号:信号变量名[信号参数类型].emit(信号的参数)

self.ageChanged[str].emit(ageInfo)

③信号关联槽函数

非默认参数的overload型信号在进行关联时必须标明参数类型,定义overload型信号时的第一个参数类型是默认参数,如ageChanged中int就是默认参数,str就是非默认参数。

boy.ageChanged.connect(resp.do_ageChanged_int) #默认参数 int型
boy.ageChanged[str].connect(resp.do_ageChanged_str) #str型参数
 

④信号断开关联 
 

boy.ageChanged[str].disconnect(resp.do_ageChanged_str) 

总结:

①信号需要定义为类属性,当创建类的实例后,PyQt5会自动将类的实例与信号绑定

②要自定义信号,类必须是QObject的子类

③代码执行过程:

关联信号和槽函数------>调用自定义类功能函数------->功能函数中执行信号发射语句------>执行槽函数(必须之前要先关联)

使用信号与槽的一些注意事项:

自定义信号时尽量不要定义overload型信号,因为python的某些类型转为c++时可能会编程同一种类型:例如dict 和 list

2.5 资源文件的使用

1.窗体可视化设计

在Qt Creator中新建一个Qt Widgets Application项目

项目名称:QtApp

Python Qt GUI与数据可视化编程(三)_第3张图片

 新建窗体类名称:Widget

Python Qt GUI与数据可视化编程(三)_第4张图片

窗体上组件的层次关系、objectName及其所属类:

 Python Qt GUI与数据可视化编程(三)_第5张图片

Python Qt GUI与数据可视化编程(三)_第6张图片

 创建完成后的窗体如下所示:

Python Qt GUI与数据可视化编程(三)_第7张图片

 2.创建和使用资源文件

File----->New File or Project----->Files and Classes---->Qt----->Qt Resource File----->创建的资源文件名为res.qrc

Python Qt GUI与数据可视化编程(三)_第8张图片

 右键res.qrc----->open in editor(打开资源文件编辑器)

资源文件最主要的功能是存储图标和图片文件,以便在程序中使用

Python Qt GUI与数据可视化编程(三)_第9张图片

 Add---->Add Prefix----->Prefix:icons(前缀就是资源的分组)

在QtApp文件夹下创建一个子目录\images,将所有的图标文件放置在这个文件夹里

Add----->Add Files---->选择图标文件(从而将图标导入到资源文件里)---->就可以在窗体设计时使用图标了

 注意:添加完资源文件后一定要先 Build----->Run qmake

目标:设置关闭按钮的图标

ui窗体设计界面---->关闭按钮的属性编辑器(右下角)----->QAbstractButton----->icon----->choose resource

 Python Qt GUI与数据可视化编程(三)_第10张图片

  结果如下

3.窗体文件和资源文件的编译

因为我是在anaconda环境下运行的python,所以在编译文件时要打开anaconda的终端

①编译资源文件

输入命令行:pyrcc5 资源文件地址 -o 资源文件名_rc.py

pyrcc5 D:\demo2022\QT_learn3\QtApp\res.qrc -o res_rc.py 

②编译.ui文件

输入命令行:pyuic5 -o ui_窗体文件名.py 窗体文件名.ui

pyuic5 -o D:\demo2022\QT_learn3\ui_widget.py D:\demo2022\QT_learn3\QtApp\widget.ui

③将编译后的资源文件res_rc.py和窗体文件ui_widget.py复制到QT_learn3文件夹中

4.窗体业务逻辑类的设计

先明确一下我们最后要得到的界面是什么样的,都有些什么功能:

Python Qt GUI与数据可视化编程(三)_第11张图片

拖动蓝色滑块,ageChanged(int)响应中会显示对应年龄,ageChanged(str)响应中会显示对应年龄的对应句子(“你是xxx”)。输入姓名后点击设置姓名,nameChanged(str)响应中会显示“Hello,xxx”

信号 槽函数
滑动滑块
on_sliderSetAge_valueChanged(self,value)
点击“设置姓名”按钮
on_btnSetName_clicked(self)
ageChanged(参数是int型)
do_ageChanged_int(self,age)
ageChanged(参数是str型)
do_ageChanged_str(self,ageInfo)
nameChanged
ameChanged(self,name)

具体代码如下所示:

import sys
from PyQt5.QtWidgets import QApplication,QWidget,QMainWindow
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtGui import QIcon

from ui_widget import Ui_Widget
from human import Human

class QmyWidget(QMainWindow,QWidget):
    def __init__(self,parent=None):
        super().__init__(parent) #调用父类构造函数
        self.ui = Ui_Widget() #创建ui对象

        self.ui.setupUi(self) #构造ui,为什么参数是self,传一个QWidget对象进去为什么输出是一个什么都没有的框

        self.boy = Human("Boy",16)
        self.boy.nameChanged.connect(self.do_nameChanged)
        self.boy.ageChanged.connect(self.do_ageChanged_int)
        self.boy.ageChanged[str].connect(self.do_ageChanged_str)


    ##========由connectSlotsByName()自动与组件的信号关联的槽函数========
    def on_sliderSetAge_valueChanged(self,value):
        self.boy.setAge(value)

    def on_btnSetName_clicked(self):
        hisName = self.ui.editNameInput.text() #获取editNameInput标签中输入的文本
        self.boy.setName(hisName)

    ##========自定义槽函数========
    def do_nameChanged(self,name):
        self.ui.editNameHello.setText("Hello,"+name)

    @pyqtSlot(int)
    def do_ageChanged_int(self,age):
        self.ui.editAgeInt.setText(str(age))

    @pyqtSlot(str)
    def do_ageChanged_str(self, info):
        self.ui.editAgeStr.setText(info)


if __name__ =="__main__":
    app = QApplication(sys.argv)
    icon = QIcon(":/icons/images/app.ico")
    app.setWindowIcon(icon)
    form = QmyWidget()
    form.show()
    sys.exit(app.exec_())

总结:

①在QmyWidget类中定义了2个由connectSlotsByName()自动创建连接的槽函数,定义了3个自己进行连接的槽函数。

②自动创建连接的槽函数:右键组件---->go to slot--->选择信号---->在.cpp里自动生成一个函数---->在python里定义同名函数,即槽函数

要自己创建连接的槽函数:将信号和槽函数关联起来---->执行发射信号的语句后调用槽函数

③代码运行过程:

1)滑动滑块----->调用自动创建连接的槽函数on_sliderSetAge_valueChanged()----->执行human类中的setAge函数------>发射自定义信号ageChanged和ageChanged[str]----->执行槽函数do_ageChanged_int:将年龄显示出来------>执行槽函数do_ageChanged_str:显示一句话

2)输入姓名---->点击设置姓名---->调用自动创建连接的槽函数on_btnSetName_clicked---->执行human类中的setName函数---->发射自定义信号nameChanged---->执行槽函数do_nameChanged:显示“Hello,xxx”

④QT_learn3项目中的所有文件

Python Qt GUI与数据可视化编程(三)_第12张图片                Python Qt GUI与数据可视化编程(三)_第13张图片

遇到的问题:

①刚开始QmyWidget类继承的父类只有QWidget,运行后报错:

 网上说setCentralWidget这个属性是在类QMainWindow中的,然后我就又加了个父类QMainWindow

继续报错:

 网上说与继承父类的顺序有关(这里没看懂,以后来好好学面向对象),把QMainWindow写前面

class QmyWidget(QMainWindow,QWidget)

②self.ui.setupUi(self),这里如果传入的参数是widget = QWidgets.QWidget(),为什么出来的就是一个什么都没有的界面


你可能感兴趣的:(Qt,python,qt)