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

然後在程序中調用靜態函數動態加載:

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);
        }
    }
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章