【QT】资源系统

Qt资源系统

Qt资源系统是一种跨平台的机制,用于将二进制文件存储在应用程序的可执行文件中。如果您的应用程序始终需要一定的文件集(如图标、翻译文件等),并且不希望丢失这些文件,这将非常有用。

资源系统基于qmake(Qt的构建工具)、rcc(Qt的资源编译器)和QFile之间的紧密协作。

资源集合文件(.qrc

与应用程序相关联的资源在一个 .qrc 文件中指定,这是一种基于 XML 的文件格式,列出了磁盘上的文件,并可选择性地为它们分配一个资源名称,应用程序必须使用该名称来访问该资源。

以下是一个 .qrc 文件的示例:

<!DOCTYPE RCC><RCC version="1.0">
<qresource>
    <file>images/copy.png</file>
    <file>images/cut.png</file>
    <file>images/new.png</file>
    <file>images/open.png</file>
    <file>images/paste.png</file>
    <file>images/save.png</file>
</qresource>
</RCC>

.qrc 文件中列出的资源文件是应用程序源代码树的一部分。指定的路径是相对于包含 .qrc 文件的目录的。请注意,列出的资源文件必须位于与 .qrc 文件相同的目录中,或者其子目录之一。

资源数据可以编译到二进制文件中,因此可以立即在应用程序代码中访问,或者可以创建一个二进制资源,并在以后的应用程序代码中向资源系统注册。

默认情况下,资源在应用程序中以与它们在源代码树中相同的文件名访问,具有 :/ 前缀,或者通过具有 qrc 方案的 URL 访问。

例如,文件路径 :/images/cut.png 或 URL qrc:///images/cut.png 将使得 cut.png 文件可访问,其在应用程序源代码树中的位置为 images/cut.png。这可以通过 file 标签的 alias 属性进行更改:

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

然后,该文件可以从应用程序中作为 :/cut-img.png 访问。还可以使用 qresource 标签的 prefix 属性为 .qrc 文件中的所有文件指定路径前缀:

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

在这种情况下,文件可作为 :/myresources/cut-img.png 访问。

某些资源需要根据用户的语言环境更改,例如翻译文件或图标。这可以通过在 qresource 标签中添加 lang 属性,并指定适当的区域设置字符串来完成。例如:

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

如果用户的语言环境是法语(即,QLocale::system().name() 返回 “fr_FR”),:/cut.jpg 将成为对 cut_fr.jpg 图像的引用。对于其他语言环境,则使用 cut.jpg

请参阅 QLocale 文档以了解区域设置字符串的格式。

另请参阅 QFileSelector 以获取另一个机制,用于选择特定于语言环境的资源,以及选择特定于操作系统的和其他功能。

外部二进制资源

要创建外部二进制资源,您必须通过将 -binary 开关传递给 rcc(Qt的资源编译器)来创建资源数据(通常使用 .rcc 扩展名)。一旦创建了二进制资源,您就可以使用 QResource API 注册该资源。

例如,可以按以下方式编译在 .qrc 文件中指定的一组资源数据:

rcc -binary myresource.qrc -o myresource.rcc

在应用程序中,可以使用以下代码注册此资源:

QResource::registerResource("/path/to/myresource.rcc");

编译入二进制文件的资源

要将资源编译到二进制文件中,必须在应用程序的 .pro 文件中提到 .qrc 文件,以便 qmake 知道它。例如:

RESOURCES     = application.qrc

qmake 将生成用于生成名为 qrc_application.cpp 的文件的 make 规则,并将其链接到应用程序中。此文件包含所有图像和其他资源的数据,作为压缩二进制数据的静态 C++ 数组。每当 .qrc 文件更改或它引用的文件更改时,qrc_application.cpp 文件都会自动重新生成。如果您不使用 .pro 文件,您可以手动调用 rcc,或者将构建规则添加到您的构建系统中。

在这里插入图片描述

Qt for Python 应用程序中的资源

资源集合文件通过使用资源编译器 rcc 转换为 Python 模块:

rcc -g python application.qrc > application_rc.py

在应用程序中,需要导入该模块:

import application_rc.py

压缩

rcc 试图对内容进行压缩,以优化最终二进制文件的磁盘空间使用。默认情况下,它会执行启发式检查,以确定是否值得进行压缩,并在未能充分压缩时将内容存储为未压缩。要控制阈值,您可以使用 -threshold 选项,告诉 rcc 必须获得原始文件大小的百分比,以便将文件存储为压缩形式。

rcc -threshold 25 myresources.qrc

默认值为 “70”,表示压缩文件必须比原始文件小 70%(不超过原始文件大小的 30%)。

如果需要,可以关闭压缩。如果您的资源已经包含了压缩格式,比如 .png 文件,并且您不想在构建时承担确认无法压缩的成本,这可能很有用。另一个原因是,如果磁盘使用量不成问题,而应用程序更希望将内容保持为干净的内存页面,则可以关闭压缩。您可以通过使用 -no-compress 命令行参数来实现。

rcc -no-compress myresources.qrc

rcc 还可以控制压缩级别和压缩算法,例如:

rcc -compress 2 -compress-algo zlib myresources.qrc

还可以在 .qrc file 标签中使用 threshold、compress 和 compress-algo 作为属性。

<qresource>
    <file compress="1" compress-algo="zstd">data.txt</file>
</qresource>

上述内容将选择 zstd 算法并使用压缩级别 1。

rcc 支持以下压缩算法和压缩级别:

  • best:使用下面列出的最佳算法中的一个,并在其最高压缩级别上获得最大的压缩,以获得最大的压缩,以牺牲大量 CPU 时间进行编译。在 XML 文件中,此值表示应最大压缩文件,而不管 rcc 支持哪些算法。
  • zstd:使用 Zstandard 库来压缩内容。有效的压缩级别范围为 1 到 19,1 表示最低压缩(CPU 时间最少),19 表示最高压缩(CPU 时间最多)。默认级别为 14。特殊值 0 告诉 zstd 库选择一个实现定义的默认值。
  • zlib:使用 zlib 库来压缩内容。有效的压缩级别范围为 1 到 9,1 表示最低压缩(CPU 时间最少),9 表示最高压缩(CPU 时间最多)。特殊值 0 表示 “无压缩”,不应使用。默认值是实现定义的,但通常为级别 6。
  • none:无压缩。这与 -no-compress 选项相同。

对于 Zstandard 和 zlib,支持是可选的。如果在编译时未检测到给定库,则尝试为该库传递 -compress-algo 将导致错误。如果启用了 Zstandard,则默认压缩算法为 zstd,如果未启用,则为 zlib。

在应用程序中使用资源

在应用程序中,可以在大多数地方使用资源路径,而不是普通的文件系统路径。特别是,您可以将资源路径传递给 QIcon、QImage 或 QPixmap 构造函数,而不是文件名:

    cutAct = new QAction(QIcon(":/images/cut.png"), tr("Cu&t"), this);

请参阅 Application 示例,了解使用 Qt 资源系统存储其图标的实际应用程序。

在内存中,资源由资源对象树表示。树在启动时自动构建,并由 QFile 用于解析资源路径。您可以使用:/初始化的 QDir 遍历资源树从根部开始。

Qt 的资源支持搜索路径列表的概念。如果您使用 : 而不是:/作为前缀来引用资源,资源将使用搜索路径列表进行查找。搜索路径列表在启动时为空;调用 QDir::addSearchPath() 来将路径添加到搜索路径列表中。

在库中使用资源

如果您的库中有资源,您需要通过调用 Q_INIT_RESOURCE() 并传入 .qrc 文件的基本名称来强制初始化您的资源。例如:

MyClass::MyClass() : BaseClass()
{
    Q_INIT_RESOURCE(resources);

    QFile file(":/myfile.dat");
    ...
}

这确保了在静态链接的情况下将资源链接到最终应用程序二进制文件中。您应该将初始化代码放在库中使用资源的地方附近,以便库的客户端仅在使用依赖于资源的库功能时链接资源。

注意:由于 rcc 生成的资源初始化器声明在全局命名空间中,您对 Q_INIT_RESOURCE() 的调用也需要在任何命名空间之外执行。

如果库包含未在内部使用而是暴露给库的客户端使用的资源,则初始化需要在应用程序代码中进行。例如:

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    Q_INIT_RESOURCE(graphlib);

    QFile file(":/graph.png");
    ...
    return app.exec();
}

与以前一样,这确保了在静态链接的情况下将资源链接到最终应用程序二进制文件中,但也在动态链接的情况下触发了库的加载,例如插件。

类似地,如果您必须显式卸载一组资源(因为插件正在卸载或资源不再有效),您可以通过调用 Q_CLEANUP_RESOURCE() 并传入与上述相同的基本名称来强制删除您的资源。

注意:在将资源作为应用程序的一部分构建时,不需要使用 Q_INIT_RESOURCE() 和 Q_CLEANUP_RESOURCE()。

  • 19
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现系统资源监控 CPU Memory,可以使用Qt的QSystemTrayIcon和QTimer组合实现系统托盘图标和定时器的功能。具体实现步骤如下: 1. 在Qt的工程中添加QSystemTrayIcon和QTimer头文件。 2. 在窗口初始化时创建系统托盘图标,并设置托盘图标的菜单和提示信息。 3. 使用定时器定时获取系统的CPU和内存使用情况,并将获取的数据显示在托盘图标的提示信息中。 4. 在定时器的槽函数中使用Qt提供的QProcess类执行系统命令获取CPU和内存的使用情况。 下面是一个简单的示例代码: ```c++ #include <QApplication> #include <QSystemTrayIcon> #include <QMenu> #include <QTimer> #include <QProcess> int main(int argc, char *argv[]) { QApplication a(argc, argv); // 创建系统托盘图标 QSystemTrayIcon trayIcon; trayIcon.setToolTip("System Monitor"); // 创建托盘图标的菜单 QMenu *menu = new QMenu(); QAction *quitAction = new QAction("Quit", menu); connect(quitAction, &QAction::triggered, &a, &QApplication::quit); menu->addAction(quitAction); trayIcon.setContextMenu(menu); // 创建定时器并启动 QTimer timer; timer.start(1000); QObject::connect(&timer, &QTimer::timeout, [&]() { // 执行系统命令获取CPU和内存的使用情况 QProcess process; process.start("sh", QStringList() << "-c" << "top -bn1 | grep load | awk '{printf \"CPU: %.2f%%\", $(NF-2)}'; free -m | awk 'NR==2{printf \" Memory: %s/%sMB (%.2f%%)\", $3,$2,$3*100/$2}'"); process.waitForFinished(); QString result = process.readAll(); trayIcon.setToolTip(result); }); // 显示系统托盘图标 trayIcon.show(); return a.exec(); } ``` 在定时器的槽函数中,我们使用QProcess执行了两个系统命令,分别是top和free,通过管道符将它们的输出传递给awk命令进行处理,最终得到CPU和内存的使用情况。然后将获取的结果设置为托盘图标的提示信息即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值