pyside6(1):Qt 资源系统和qrc文件使用

1.Qt资源系统简介

Qt 资源系统是一种独立于平台的资源管理器,用于在应用程序的可执行文件中存储二进制文件。如果应用程序始终需要一组特定的文件(图标、翻译文件等),使用Qt资源管理系统可以有效防止应用文件丢失。简而言之,Qt资源系统就是桌面应用中的静态文件管理器。

 Qt资源系统基于qmakerccQt 的资源编译器)和QFile

2.qrc文件

qrc是一种基于XML格式的文件,应用使用的资源文件在拓展名为qrc的文件中声明。qrc文件中声明的资源文件是应用源代码的一部分,其中的文件路径是相对于qrc文件所在目录的相对路径。因此qrc中声明的资源文件必须和qrc文件处于同一目录或者是该目录的子目录

资源文件可以直接随源代码编译到应用可执行文件中,在代码中直接调用,也可以先创建资源文件然后使用代码注册到资源系统中。例如声明一张图片:

<file>images/cut.png</file>

3.引用资源

声明资源后,可以在程序中用:/前缀或者以qrc为命名的URL访问。例如引用相对于qrc文件所在目录的图片images/cut.png可以用:/images/cut.png或者qrc:///images/cut.png

如果不想每次都输入这么长的路径,可以使用alias属性,即

<file alias="cut-img.png">images/cut.png</file>

这样可以使用:/cut.png访问图片images/cut.png

4.路径前缀

使用路径前缀可以将不同目录下的文件组合到一个命名空间中,便于在不移动文件的前提下,以统一的路径前缀访问不同路径下文件,相当于对文件做了虚拟分类。

<qresource prefix="/myresources">
 <file alias="cut-img.png">images/cut.png</file>
 <file alias="icon.png">icons/icon.png</file>
</qresource>

现在可以使用:/myresources/cut-img.png访问cut-img.png, 使用:/myresources/icon.png访问icon.png

注意

(1)不加别名时,文件引用方式是:/文件相对于qrc文件路径,例如

<file >images/cut.png</file>

的引用方式是 :/images/cut.png

(2)加前缀时,文件引用方式是:/前缀/文件相对于qrc文件路径

<file prefix="/icon">images/cut.png</file>

变为:/icon/images/cut.png

(3)加别名和前缀时:/前缀/文件别名

<qresource prefix="/icon">
 <file alias="cut-img.png">images/cut.png</file>
</qresource>

变为 :/icon/cut.png

5.文件国际化

有些时候应用可能需要在不同的语言环境下使用不同的文件,使用lang属性可以轻松做到这一点:

<qresource>
    <file>cut.jpg</file>
</qresource>
<qresource lang="fr">
    <file alias="cut.jpg">cut_fr.jpg</file>
</qresource>

当系统语言切换成法语时,对cut.jpg的引用将会自动切换成cut_fr.jpg,当系统语言是其它语言时,将会引用cut.jpg

6.编译qrc文件为python模块

要在pyside6项目中引用qrc文件,需要使用rcc工具将其编译为python模块,编译工具是pyside6-rcc。例如下面的qrc文件:

<RCC>
    <qresource prefix="/icon">
        <file>icon/ic_last_step.svg</file>
        <file>icon/ic_next_step.svg</file>
        <file>icon/ic_start.svg</file>
    </qresource>
</RCC>

qrc文件所在目录运行 编译命令:

 pyside6-rcc res.qrc -o res.py

生成res.py 即资源模块

7.应用示例

下面以设置应用按钮图标为例说明如何使用Qt资源管理器管理图标文件。图标文件可以从阿里云图标库下载:iconfont-阿里巴巴矢量图标库

(1)创建图标qrc文件

新建一个pyside6项目,目录结构如下:

 将图标保存在resource/icon下。

小技巧

pycharm中直接编辑qrc文件很繁琐,使用Pyside6开发Qt程序的老铁们不妨装一个官方的QtCreator,这样可以快速编辑很多Qt文件,还有很多代码示例可以看,另外还可以用QtCreator快速生成很多模板代码,排查Qt文件中错误等。

Q:为啥不直接用QtCreator开发Pyside6项目?

A:QtCreator的代码编辑器太垃圾了,使用Pycharm快到飞起。

 现在打开QtCreator新建这个res.qrc文件,把图标路径加进来:

 创建文件后,先添加一个icon前缀:

然后使用Add Files按钮把图标文件添加到路径中,然后保存:

 现在得到以下的qrc文件:res.qrc

<RCC>
    <qresource prefix="/icon">
        <file>icon/ic_last_step.svg</file>
        <file>icon/ic_next_step.svg</file>
        <file>icon/ic_start.svg</file>
    </qresource>
</RCC>

为了缩短引用路径,给每个图标文件取个别名(alias):

 现在得到这样的qrc文件:

<RCC>
    <qresource prefix="/icon">
        <file alias="ic_last_step">icon/ic_last_step.svg</file>
        <file alias="ic_next_step">icon/ic_next_step.svg</file>
        <file alias="ic_start">icon/ic_start.svg</file>
    </qresource>
</RCC>

 (2)编译qrc文件为python模块

在这个qrc文件所在目录运行命令:

 pyside6-rcc res.rc -o res.py

 如果不在这个目录运行,res.qrcres.py要改成绝对路径或者相对于命令运行目录的相对路径。

运行完可以看到res.qrc文件所在目录多了一个res.py文件,打开看看:

# Resource object code (Python 3)
# Created by: object code
# Created by: The Resource Compiler for Qt version 6.1.3
# WARNING! All changes made in this file will be lost!

from PySide6 import QtCore

qt_resource_data =b"......"

qt_resource_name = b"......"

qt_resource_struct = b"......"


def qInitResources():
    QtCore.qRegisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)


def qCleanupResources():
    QtCore.qUnregisterResourceData(0x03, qt_resource_struct, qt_resource_name, qt_resource_data)


qInitResources()

可以看到文件中包含三个二进制编码的字符串: 

qt_resource_dataqrc源码,其中还包含了矢量图标的svg代码。

qt_resource_name:资源名称;

qt_resource_struct:资源二进制文件结构;

还有两个Python函数:

qInitResources:初始化资源,调用了qRegisterResourceData方法在应用中注册资源。qCleanupResources:清除资源,调用了qUnregisterResourceData方法在应用中卸载资源。

提示

编译完成后,资源源文件可以删除了,比如上述icon中的图标文件可以全部删除。

(2)在程序中引用资源文件

创建main.py

import random
import sys

from PySide6 import QtWidgets, QtCore
from PySide6.QtGui import QPixmap, QIcon
from PySide6.QtWidgets import QGridLayout
import resource.res as res


class MyWidget(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()

        self.text = QtWidgets.QLabel("Hello World")

        self.layout = QtWidgets.QVBoxLayout(self)
        self.layout.addWidget(self.text)
        # 按钮布局
        self.btn_layout = QGridLayout()
        # 创建三个按钮
        self.button_last_step = QtWidgets.QPushButton()
        # 按钮图标
        self.button_last_step.setIcon(QPixmap(":/icon/ic_last_step"))
        self.btn_layout.addWidget(self.button_last_step, 0, 0)

        self.button_start = QtWidgets.QPushButton()
        self.button_start.setIcon(QPixmap(":/icon/ic_start"))
        self.btn_layout.addWidget(self.button_start, 0, 1)

        self.button_next_step = QtWidgets.QPushButton()
        self.button_next_step.setIcon(QPixmap(":/icon/ic_next_step"))
        self.btn_layout.addWidget(self.button_next_step, 0, 2)
        # 添加按钮布局到窗口布局中
        self.layout.addLayout(self.btn_layout)


if __name__ == "__main__":
    app = QtWidgets.QApplication([])
    widget = MyWidget()
    widget.resize(400, 300)
    widget.show()
    sys.exit(app.exec())

运行效果:

猜你喜欢

转载自blog.csdn.net/anbuqi/article/details/120455219