0.前言
對於簡單的應用,我們可以直接讀取 QSS 樣式表文件來實現換膚。但一般樣式裏還帶有圖片等資源的路徑,如果通過相對路徑來加載,不便於管理,不過好處是替換圖片方便。我們也可以使用 Qt 的 rcc.exe 工具將資源文件生成爲二進制文件,在程序中使用 QResource 進行動態加載。
1.正文
Qt 資源系統是一種與平臺無關的機制,用於在應用程序的可執行文件中存儲二進制文件。如果你的應用程序始終需要一組特定的文件(圖標,翻譯文件等),這將很有用。
手動修改 qrc 的 xml 文件我感覺有點麻煩,還不如單獨建個工程來管理不同皮膚的 qrc ,然後使用 rcc 生成爲二進制資源文件(Win 下用 QtCreator 編譯器對應的 Cmd,可以切換到 qrc 目錄執行,rcc 還提供壓縮功能詳情見文檔):
rcc -binary myresource.qrc -o myresource.rcc
然後在程序中調用靜態函數動態加載:
QResource::registerResource("/path/to/myresource.rcc");
參考 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_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
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);
}
}
}