PyQt5-资源文件的使用
窗体可视化设计
新建一个Qt Widgets Application项目QtApp,创建窗体时选择窗体基类为QWidget,新建窗体类的名称设置为默认的Widegt。创建项目后,对窗体Widget.ui进行可视化设计,设计好的窗体如下图所示。
该窗体在设计时采用了布局管理方法。“年龄设置”分组框用的是组件面板Container分组里的GroupBox组件,其内部组件按网格状布局;“姓名设置”分组框里的组件也按网格状布局;最下方的按钮和多个空格组件使用了组件面板Container分组里的Frame组件作为容器,采用水平布局。窗口的主布局采用垂直布局。
窗体上所有组件的层次关系如下图所示,下图还显示了各个组件的objectName及其所属的类。用于设置年龄的是一个QSlider组件,在属性编辑器里设置其minimum属性为0,maximum属性为100。
创建和使用资源文件
其中 图标可以去阿里巴巴图标网
https://www.iconfont.cn/user/detail?spm=a313x.7781069.1998910419.dfa9d9a29&uid=9992
进行获取
在资源浏览器中
点击编辑资源
将图标导入到资源文件里后,就可以在窗体设计时使用图标了。例如,要设置“关闭”按钮的图标,在属性编辑器中有icon属性,点击右侧下拉菜单中的“ChooseResource...”,就可以在项目的资源文件里为按钮选择图标了。
窗体文件和资源文件的编译
在Qt Creator里设计的资源文件要在Python程序里使用,需要使用pyrcc5.exe工具软件将资源文件res.qrc编译为一个对应的Python文件res_rc.py。执行编译的指令如下:
那么这里 先将自己设计好的ui转为py文件
窗体业务逻辑类的设计
将上个示例创建的文件human.py复制到本示例目录下。
human.py文件的代码如下:
## 自定义信号与槽的演示
import sys
from PyQt5.QtCore import QObject,pyqtSlot,pyqtSignal
class Human(QObject):
##定义一个带str类型参数的信号
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 < age <= 35):
ageInfo = "你是年轻人"
elif (35 < age <= 55):
ageInfo = "你是中年人"
elif (55 < age <= 80):
ageInfo = "您是老人"
else:
ageInfo = "您是寿星啊"
self.ageChanged[str].emit(ageInfo)#发射str参数信号
def setName(self, name):
self._name = name
self.nameChanged.emit(self._name)
class Responsor (QObject):
@pyqtSlot(int)
def do_ageChanged_int(self,age):
print("你的年龄是:"+str(age))
@pyqtSlot(str)
def do_ageChanged_str(self, ageInfo):
print(ageInfo)
## @pyqtSlot (str)
def do_nameChanged(self,name):
print("Hello," + name)
if __name__ == "__main__":##测试程序
print("**创建对象时**")
boy=Human("Boy",16)
resp=Responsor()
boy.nameChanged.connect(resp.do_nameChanged)
##overload的信号,两个槽函数不能同名,关联时需要给信号加参数区分
boy.ageChanged.connect(resp.do_ageChanged_int)# 默认参数,int型
boy.ageChanged[str].connect(resp.do_ageChanged_str)# str型参数
print("\n**建立关联后**")
boy.setAge(35)# 发射两个ageChanged信号
boy.setName("Jack") # 发射nameChanged信号
boy.ageChanged[str].disconnect(resp.do_ageChanged_str) # 断开关联
print("\n **断开ageChanged[str]的关联后**")
boy.setAge(10)
# 发射两个ageChanged信号
采用单继承方法设计一个窗体业务逻辑类QmyWidget,保存为文件myWidget.py,该文件的完整内容如下:
import sys
from PyQt5.QtWidgets import QWidget,QApplication
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtGui import QIcon
from ui_QtAPP import Ui_Form
from human import Human
class QmyWidget(QWidget):
def __init__(self,parent=None):
super().__init__(parent) #调用父类构造函数
self.ui=Ui_Form() #创建UI对象
self.ui.setupUi(self) #构造UI
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_horizontalSlider_valueChanged(self,value):
self.boy.setAge(value)
def on_pushButton_clicked(self):
hisName=self.ui.lineEdit_3.text()
self.boy.setName(hisName)
## =======自定义槽函数=======
def do_nameChanged(self,name):
self.ui.lineEdit_4.setText("Hello,"+name)
@pyqtSlot(int)
def do_ageChanged_int(self, age):
self.ui.lineEdit.setText(str(age))
@pyqtSlot(str)
def do_ageChanged_str(self, info):
self.ui.lineEdit_2.setText(info)
if __name__ == "__main__": ##用于当前窗体测试
app=QApplication(sys.argv)
icon=QIcon(":/icon/img1.png")
app.setWindowIcon(icon)
form=QmyWidget()
form.show()
sys.exit(app.exec_())
程序myWidget.py可以当作主程序直接运行,但是建议单独编写一个主程序文件appMain.py,此文件的代码如下:
## GUI应用程序主程序
import sys
from PyQt5.QtWidgets import QApplication
from myWidget import QmyWidget
app = QApplication(sys.argv) # 创建app,用QApplication类
myWidget = QmyWidget() #创建窗体
myWidget.show()
sys.exit(app.exec_())
整个项目的框架如下所示:
整体效果如下:
为应用程序设置图标
可以为应用程序设置一个图标,这样,应用程序的每个窗体将自动使用这个图标作为窗体的图标。在myWidget.py文件的测试程序部分添加设置应用程序图标的代码:
就是从资源文件里提取了一个图标作为应用程序的图标。当然,也可以使用QWidget的setWindowIcon()函数为一个窗体单独设置图标。
上述程序中应用程序没有显示图标 是因为代码后面有误
正确代码为
if __name__ == "__main__": ##用于当前窗体测试
app=QApplication(sys.argv)
icon=QIcon(":icon/img1.png")
app.setWindowIcon(icon)
form=QmyWidget()
form.show()
sys.exit(app.exec_())
所以最终的全部代码为:
import sys
from PyQt5.QtWidgets import QWidget,QApplication
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtGui import QIcon
from ui_QtAPP import Ui_Form
from human import Human
class QmyWidget(QWidget):
def __init__(self,parent=None):
super().__init__(parent) #调用父类构造函数
self.ui=Ui_Form() #创建UI对象
self.ui.setupUi(self) #构造UI
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_horizontalSlider_valueChanged(self,value):
self.boy.setAge(value)
def on_pushButton_clicked(self):
hisName=self.ui.lineEdit_3.text()
self.boy.setName(hisName)
## =======自定义槽函数=======
def do_nameChanged(self,name):
self.ui.lineEdit_4.setText("Hello,"+name)
@pyqtSlot(int)
def do_ageChanged_int(self, age):
self.ui.lineEdit.setText(str(age))
@pyqtSlot(str)
def do_ageChanged_str(self, info):
self.ui.lineEdit_2.setText(info)
if __name__ == "__main__": ##用于当前窗体测试
app=QApplication(sys.argv)
icon=QIcon(":icon/img1.png")
app.setWindowIcon(icon)
form=QmyWidget()
form.show()
sys.exit(app.exec_())
效果如下: