【Qt】Qt换肤,使用QResource动态加载资源文件
【Qt】使用QResource动态加载资源文件
0.前言
对于简单的应用,我们可以直接读取 QSS 样式表文件来实现换肤。但一般样式里还带有图片等资源的路径,如果通过相对路径来加载,不便于管理,不过好处是替换图片方便。我们也可以使用 Qt 的 rcc.exe
工具将资源文件生成为二进制文件,在程序中使用 QResource
进行动态加载。
1.正文
Qt 资源系统是一种与平台无关的机制,用于在应用程序的可执行文件中存储二进制文件
。如果你的应用程序始终需要一组特定的文件(图标,翻译文件等),这将很有用。
手动修改 qrc 的 xml 文件我感觉有点麻烦,还不如单独建个工程来管理不同皮肤的 qrc ,然后使用 rcc 生成为二进制资源文件(Win 下用 QtCreator 编译器对应的 Cmd,可以切换到 qrc 目录执行,rcc 还提供压缩功能详情见文档):
rcc -binary myresource.qrc -o myresource.rcc
rcc -binary myresource.qrc -o myresource.dll
然后在程序中调用静态函数动态加载:
QResource::registerResource("/path/to/myresource.rcc");
QResource::registerResource("/path/to/myresource.dll");
如果vs安装了qt-vsaddin-msvc2022*exe 插件,也可以右键qrc 文件设置 然后代码里面QResource::registerResource("/path/to/myresource.dll");
参考 Qt 文档(QResource ):https://doc.qt.io/qt-5/qresource.html
参考 Qt 文档(Qt 资源系统):https://doc.qt.io/qt-5/resources.html
2.实现
实现效果:
代码链接:
github 链接:https://github.com/gongjianbo/MyTestCode/tree/master/Qt/QtSwitchSkin
主要代码(样式表和图片在资源文件中):
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();void loadSkin(const QString &paths);private:Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"#include <QResource>
#include <QFile>
#include <QApplication>
#include <QDebug>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);//为什么不用combobox?因为按钮样式更简单//可以在启动时读取目录下皮肤文件作为combobox的选项connect(ui->btnWhite,&QPushButton::clicked,this,[=](){loadSkin("white.rcc");});connect(ui->btnBlack,&QPushButton::clicked,this,[=](){loadSkin("black.rcc");});//加载默认样式loadSkin("white.rcc");
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::loadSkin(const QString &paths)
{static QString old_paths;if(paths.isEmpty()||paths==old_paths)return;//先卸载当前的资源if(!old_paths.isEmpty()){const bool unresult=QResource::unregisterResource(old_paths);qDebug()<<"QResource::unregisterResource"<<unresult;}old_paths=paths;//加载资源文件const bool result=QResource::registerResource(paths);qDebug()<<"QResource::registerResource"<<result;if(result){//设置样式表QFile file(":/style.qss");if(file.open(QIODevice::ReadOnly)){const QString qss_str=file.readAll();qApp->setStyleSheet(qss_str);}}
}