一、簡介
在項(xiàng)目實(shí)踐中,最簡單的更新應(yīng)用UI交互的方式就是更新整個安裝包。
隨著業(yè)務(wù)的發(fā)展,一個客戶端需要同時適配多種業(yè)務(wù),每種業(yè)務(wù)都有自己獨(dú)特的設(shè)置頁,業(yè)務(wù)之間又較為獨(dú)立。如果將這些UI頁面、業(yè)務(wù)代碼都在一份代碼上維護(hù),加各種條件分支,維護(hù)會越來越困難:容易出錯、程序體積增大、測試工作量增加,而且無法滿足快速迭代的需求。
因此,如果能針對不同業(yè)務(wù),提供各異的插件、描述文件動態(tài)更新UI交互,就能比較好的滿足業(yè)務(wù)需求。而且動態(tài)UI只需要更新插件、描述文件,也能夠運(yùn)行時更新,對用戶體驗(yàn)、客戶端其它功能影響能夠降到非常低。
本文基于Qt(5.12.12)、C++客戶端開發(fā)(Visual Studio 2017),整理了一套較為完善的動態(tài)UI方案。
Qt提供了QUiLoader,支持在程序運(yùn)行時,加載.ui(Qt定義的XML)來動態(tài)更新UI頁面,還能以Qt插件的方式將自定義控件也加入.ui。另外,還可以通過運(yùn)行時加載rcc文件的方式,動態(tài)更新指定程序所用資源,包括圖標(biāo)、動圖、樣式表等等;同時,也能減少程序包體積,比如將不常用到的資源在需要用到時再下載解析。當(dāng)然,樣式表.qss
本身就支持運(yùn)行時加載,常用于程序換膚功能。
本文從QUiLoader加載UI頁面出發(fā),圍繞Qt、C++動態(tài)加載UI,較全面的介紹QUiLoader、Qt資源管理、Qt插件的創(chuàng)建及使用。
二、QUiLoader
使用QUiLoader需要引入模塊UI tools。模塊引入后exe體積增長情況如下:
exe體積增長 | |
---|---|
release | 約436KB |
debug | 約907KB |
將.ui添加到.qrc,或指定絕對路徑,參考下面代碼:
QtWidgetsApplication1::QtWidgetsApplication1(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
QUiLoader loader;
QFile file(":/QtWidgetsApplication1/Widget.ui");
/* 或QFile file(R"(E:/work src/test/QtWidgetsApplication1/QtWidgetsApplication1/Widget.ui)"); */
file.open(QFile::ReadOnly);
QWidget *myWidget = loader.load(&file, this);
file.close();
auto *layout = new QVBoxLayout;
layout->addWidget(myWidget);
ui.centralWidget->setLayout(layout);
}
先用QFile從指定路徑負(fù)責(zé)讀取.ui,然后調(diào)用QUiLoader::load
接口從.ui中加載出QWidget*
,再將該QWidget*
添加到指定父頁面上。當(dāng)然,經(jīng)過在Qt5.12.12上的實(shí)踐,.ui也可以是由QWidget、QDialog、QFrame或QMainWindow等作為頂層窗體。另外,.ui 的頂層窗體可以有布局,也可以是沒布局。可見,基本上通過Qt Designer能生成的.ui,QUiLoader都能動態(tài)加載出來。
相比于直接把.ui轉(zhuǎn)成C++代碼編進(jìn)程序,QUiLoader支持在運(yùn)行期間直接根據(jù).ui生成對應(yīng)頁面,提供了更大的可能性,比如同一份.ui可以在完全不同的業(yè)務(wù)中加載出來,而無需依賴某個類或.h。
另外,如果需要在QUiLoader加載的.ui頁面跟程序中connect信號、槽,可以通過下面方式查找對象、定義信號/槽:
/* 1.查找名稱為“testBtn”QPushButton */
QPushButton *getButton = getWidget->findChild<QPushButton *>("testBtn");
/* 2.查找所有QPushButton */
QList<QPushButton *> getAllPButtons = getWidget->findChildren<QPushButton *>();
QMetaObject::connectSlotsByName(this); /* 該函數(shù)會將this的所有子對象都連接上一個槽(slot),槽的命名規(guī)范為on_對象名_信號名,比如上面的setButton的clicked(),將會生成一個on_setButton_clicked()的槽,你只要實(shí)現(xiàn)該槽函數(shù)就可以了 */
在實(shí)際項(xiàng)目中,.ui往往并非由Qt基本控件、基本樣式組成,我們還需要往.ui里面添加一些自定義控件。
Qt官方文檔中沒有描述當(dāng).ui包含自定義控件時,如何用QUiLoader加載。按照傳統(tǒng).ui轉(zhuǎn)成C++編進(jìn)exe的方式,將基本控件“提升為”項(xiàng)目中的自定義控件類,如派生自QWidget的子類CustomWidget,用QUiLoader加載.ui,CustomWidegt“退化為“普通的QWidget,且errorString()
不會輸出任何錯誤。
重新看了下QUiLoader的接口,發(fā)現(xiàn)QUiLoader提供了void QUiLoader::addPluginPath(const QString& path)
接口,因此QUiLoader支持的應(yīng)該是通過Qt插件添加自定義控件的方式。
我們可以基于QtUiPlugin/QDesignerCustomWidgetInterface
創(chuàng)建Qt插件,而Qt+VS也提供了創(chuàng)建這種插件項(xiàng)目的方式,接下來一章我們闡述下Qt插件及其創(chuàng)建和應(yīng)用。
三、Qt插件
1、項(xiàng)目創(chuàng)建
基于Qt5.12.12版本,你可以創(chuàng)建Qt插件項(xiàng)目,
本文創(chuàng)建的Qt插件項(xiàng)目,命名為CustomWidget。創(chuàng)建完項(xiàng)目后,就會默認(rèn)生成CustomWidgetPlugin類:
#pragma once
#include <QtUiPlugin/QDesignerCustomWidgetInterface>
class CustomWidgetPlugin : public QObject, public QDesignerCustomWidgetInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetInterface" FILE "customwidgetplugin.json")
Q_INTERFACES(QDesignerCustomWidgetInterface)
public:
CustomWidgetPlugin(QObject *parent = Q_NULLPTR);
bool isContainer() const;
bool isInitialized() const;
QIcon icon() const;
QString domXml() const;
QString group() const;
QString includeFile() const;
QString name() const;
QString toolTip() const;
QString whatsThis() const;
QWidget *createWidget(QWidget *parent);
void initialize(QDesignerFormEditorInterface *core);
private:
bool initialized;
};
CustomWidgetPlugin的基類QDesignerCustomWidgetInterface定義了比較完備的接口(純虛函數(shù)),
class QDesignerCustomWidgetInterface
{
public:
virtual ~QDesignerCustomWidgetInterface() {}
virtual QString name() const = 0;
virtual QString group() const = 0;
virtual QString toolTip() const = 0;
virtual QString whatsThis() const = 0;
virtual QString includeFile() const = 0;
virtual QIcon icon() const = 0;
virtual bool isContainer() const = 0;
virtual QWidget *createWidget(QWidget *parent) = 0;
virtual bool isInitialized() const { return false; }
virtual void initialize(QDesignerFormEditorInterface *core) { Q_UNUSED(core); }
virtual QString domXml() const
{
return QString::fromUtf8("<widget class=\"%1\" name=\"%2\"/>")
.arg(name()).arg(name().toLower());
}
virtual QString codeTemplate() const { return QString(); }
};
2、插件使用
CustomWidget插件項(xiàng)目的編譯產(chǎn)物是CustomWidget.dll或CustomWidget.lib,在實(shí)際項(xiàng)目代碼中可以單獨(dú)使用上述CustomWidget.dll或CustomWidget.lib,不引入額外的.h,因?yàn)榻涌诿Q都是QDesignerCustomWidgetInterface定義好的。
一般可以通過QPluginLoader來加載Qt插件,并且QPluginLoader提供了load、unload接口支持熱更新。示例代碼如下:
QPluginLoader pluginLoader("CustomWidget.dll"); /* 相對路徑,根據(jù)實(shí)際路徑傳入 */
if (pluginLoader.load())
{
if (QObject *pPlugin = pluginLoader.instance())
{
auto *pCustomWidgetPlugin = dynamic_cast<QDesignerCustomWidgetInterface *>(pPlugin);
auto *pLayout = new QVBoxLayout;
pLayout->addWidget(pCustomWidgetPlugin->createWidget(this));
ui.centralWidget->setLayout(pLayout);
}
}
CustomWidgetPlugin::createWidget
本質(zhì)上是只是執(zhí)行了一段創(chuàng)建自定義控件的邏輯,因此在createWidget之后執(zhí)行pluginLoader.unload()
卸載插件,不會影響已創(chuàng)建的自定義控件。
上述創(chuàng)建的CustomWidget插件工程目錄如下:
其中,為了方便,我添加了CustomWidget.ui用于設(shè)計(jì)CustomWidget的UI樣式。
3、效果預(yù)覽
Qt本身提供的大多數(shù)工具都是支持上述Qt插件的,包括Qt Creator、Qt Designer等等。我們開發(fā)和使用插件項(xiàng)目時,也會希望能實(shí)時預(yù)覽插件在項(xiàng)目中的效果,那么就可以把開發(fā)的插件“添加”到Qt Designer中去。
我使用的是Visual Studio 2017+Qt5.12.12開發(fā),需要將CustomWidget.dll放到
D:\Qt\Qt5.12.12\5.12.12\msvc2017\plugins\designer
或D:\Qt\Qt5.12.12\5.12.12\msvc2017_64\plugins\designer
。
注意,需要保證32位、64位對應(yīng),否則Qt Designer識別不到。
你可以打開Qt Designer,在幫助-關(guān)于插件中刷新查看CustomWidget.dll的加載情況,
上面是因?yàn)槲曳诺腃ustomWidget.dll是debug版本,而Qt Designer要求使用release版本,重新編譯放置后,
在Qt Designer中,添加到.ui并加載出來了我所創(chuàng)建的Qt插件CustomWidget.dll,Qt Designer本身有預(yù)覽效果的功能:
QtWidgetsApplication1::QtWidgetsApplication1(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
QUiLoader loader;
loader.addPluginPath(R"(E:/test/QtWidgetsApplication1/Release/)");
QFile file(R"(E:/work src/test/QtWidgetsApplication1/QtWidgetsApplication1/Widget.ui)");
file.open(QFile::ReadOnly);
QWidget *myWidget = loader.load(&file, this);
file.close();
const auto result = loader.errorString();
auto *layout = new QVBoxLayout;
layout->addWidget(myWidget);
ui.centralWidget->setLayout(layout);
}
Qt Designer中預(yù)覽效果:
圖中“插件子頁面”文本所示W(wǎng)idget即插件顯示效果。為了驗(yàn)證效果,只是簡單的添加了個文本,在.ui中給CustomWidget設(shè)置了樣式如下:
background-color: rgb(170, 255, 255)
實(shí)際加載CustomWidget.dll效果:
另外,發(fā)現(xiàn)release的工程能加載release和debug的插件,但debug的工程只能加載debug的插件,若加載release的插件依然失敗,且errorString()
不輸出任何問題。
QUiLoader加載Qt插件后,還可以通過QUiLoader::availableWidgets
接口自由創(chuàng)建插件對應(yīng)的UI頁面,
QWidget *loadCustomWidget(QWidget *parent)
{
QUiLoader loader;
QWidget *myWidget;
QStringList availableWidgets = loader.availableWidgets();
if (availableWidgets.contains("CustomWidget"))
myWidget = loader.createWidget("CustomWidget", parent);
return myWidget;
}
完成了帶自定義控件的.ui加載之后,還有一個問題,就是.ui可能包含一些圖標(biāo)、項(xiàng)目中復(fù)用的樣式(如皮膚)資源,通常通過.qrc來進(jìn)行加載。
而我們運(yùn)行時動態(tài)加載的.ui本身是不包含.qrc的,那么這個.ui中的圖標(biāo)、樣式怎么加載呢?
四、Qt資源管理
在Qt中,我們既可以用Qt Designer直接在.ui中指定控件的圖標(biāo)資源路徑(樣式表的規(guī)則可以參考我的另一篇博客),
也可以在使用具體Qt控件時傳入路徑,
QPixmap testPixmap(":/QtWidgetsApplication1/src/qt.png");
QRect testRect; /* TODO:賦值 */
painter->drawPixmap(testRect.x(), testRect.y(), testPixmap, testRect.width(), 0, testRect.width(), testRect.height());
而上述圖標(biāo)路徑跟具體某個.qrc
無關(guān),即程序運(yùn)行后如果有一個.qrc
中包含該路徑資源,就能加載出對應(yīng)圖標(biāo)。
通過實(shí)踐發(fā)現(xiàn),如果在.ui中添加或不添加圖標(biāo)資源對應(yīng)的.qrc
,不影響最終程序運(yùn)行時該圖標(biāo)的加載,只是在Qt Designer中無法根據(jù).ui預(yù)覽該圖標(biāo)。
也就是說,不光是本文中用QUiLoader運(yùn)行時加載的Widget.ui中使用了某個圖標(biāo)資源路徑,還是Qt插件CustomWidget.dll中使用了,只要程序運(yùn)行時存在任意一份.qrc里包括了該圖標(biāo)資源,就能成功加載出來。
當(dāng)然,如果運(yùn)行時程序中沒有找到任何匹配的圖標(biāo)資源,就會不顯示任何圖標(biāo),但不影響程序運(yùn)行。
如下圖所示,紅色框中是QUiLoader在程序運(yùn)行時加載的圖標(biāo),黃色框中是插件創(chuàng)建頁面中的圖標(biāo),藍(lán)色框中才是程序本身代碼中指定圖標(biāo),而這三個圖標(biāo)路徑都是對應(yīng)程序編譯進(jìn)去的同一個.qrc
中同一個圖標(biāo)。
不過,正如本文簡介中提到,我們想要的圖標(biāo)、樣式資源可能僅用于運(yùn)行時才加載的.ui或插件,并不希望程序中本身就包括,這樣才能支持運(yùn)行時連同圖標(biāo)、樣式一起更新。
那么,在運(yùn)行時怎么指定和加載.ui專屬的.qrc呢?
我們還是先來回顧下.qrc
的基本知識。
.qrc
,是Qt提供的用于管理資源的文件格式,它有兩個非常有用的特點(diǎn):
-
延遲加載:即當(dāng)你首次調(diào)用某個資源時才會申請內(nèi)存。
-
資源復(fù)用:當(dāng)你多個地方同時調(diào)用同一資源,Qt不會重復(fù)申請內(nèi)存。
.qrc
就相當(dāng)于使用了一個強(qiáng)化版本的fileCache。
1、創(chuàng)建.qrc
通??梢酝ㄟ^下圖所示創(chuàng)建.qrc
并添加到項(xiàng)目中,
我們可以把各種資源包括.png、.jpg、.qss等添加到.qrc
,主要有兩種方式,第一種是直接雙擊.qrc
使用默認(rèn)的打開方式Qt Resource Editor打開,
或者通過Qt Designer打開.ui進(jìn)入資源瀏覽器添加,
2、內(nèi)嵌資源
通過上述方式創(chuàng)建.qrc
并添加到項(xiàng)目、添加資源到.qrc
,項(xiàng)目正式編譯開始后,Qt會將.qrc
編譯成.cpp,然后再編譯、鏈接進(jìn)exe,
1>rcc QtWidgetsApplication1.qrc
1>qrc_QtWidgetsApplication1.cpp
直接打開qrc_MainApplication.cpp
可以看到,
/****************************************************************************
** Resource object code
**
** Created by: The Resource Compiler for Qt version 5.12.12
**
** WARNING! All changes made in this file will be lost!
*****************************************************************************/
static const unsigned char qt_resource_data[] = {
// E:/work src/10 ??/7?QUiLoader/QtWidgetsApplication1/QtWidgetsApplication1/src/qt.png
0x0,0x0,0xb,0xaf,
0x89,
0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,
0x0,0x0,0x40,0x0,0x0,0x0,0x40,0x8,0x6,0x0,0x0,0x0,0xaa,0x69,0x71,0xde,
0x0,0x0,0x0,0x4,0x73,0x42,0x49,0x54,0x8,0x8,0x8,0x8,0x7c,0x8,0x64,0x88,
0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0x0,0xff,0x0,0x0,0x0,0xff,
0x1,0x9d,0x85,0x40,0x1a,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x53,0x6f,0x66,
0x74,0x77,0x61,0x72,0x65,0x0,0x77,0x77,0x77,0x2e,0x69,0x6e,0x6b,0x73,0x63,0x61,
0x70,0x65,0x2e,0x6f,0x72,0x67,0x9b,0xee,0x3c,0x1a,0x0,0x0,0xb,0x2c,0x49,0x44,
0x41,0x54,0x78,0x9c,0xe5,0x5b,0x7b,0x70,0x54,0xd5,0x1d,0xfe,0xee,0xbe,0xb3,0x9b,
0xcd,0x3b,0x24,0x21,0x8f,0xd,0x24,0xc6,0x0,0x21,0x1,0x2a,0x2f,0x9,0x4,0x14,
0x4a,0x83,0xf8,0xb6,0x3e,0x28,0x76,0xd4,0x8e,0x3a,0xad,0xb5,0x63,0x8b,0xda,0x6a,
0xdb,0x91,0x47,0xb5,0x5a,0x3b,0xd3,0xa1,0xce,0x14,0xc7,0x7,0xb6,0xbe,0x46,0x19,
0xea,0xb,0x14,0x21,0x12,0x85,0x90,0x18,0xc,0x20,0x9,0x9,0x79,0x1,0x9,0x98,
0x90,0x90,0x84,0xbc,0x76,0xef,0xde,0xe7,0xb9,0xa7,0x7f,0x6c,0x12,0x89,0x7b,0xef,
0x66,0xc3,0xde,0x8d,0x71,0xfa,0xcd,0x30,0xc3,0x39,0xbf,0x6f,0xcf,0xf9,0xdd,0x2f,
0xe7,0x9c,0x7b,0xce,0xef,0xfc,0x2e,0x43,0x29,0xc5,0x58,0x70,0x16,0xbb,0xac,0x0,
0xa,0x1,0xac,0x6,0x30,0xdb,0x68,0x62,0xe2,0x67,0x14,0x38,0x5c,0xc9,0x69,0x96,
0x18,0x93,0x89,0x31,0x99,0xcc,0xc,0x65,0x18,0x86,0xf0,0x5e,0xd2,0xcb,0xf3,0x4a,
0x8b,0xc8,0xd3,0x6a,0x49,0x52,0xca,0x65,0x89,0x7e,0x5a,0xbe,0xb9,0xae,0x67,0xcc,
0xe,0xbe,0x47,0x30,0x63,0x9,0xe0,0x2c,0x76,0xdd,0xc,0x60,0x3b,0x80,0x18,0x0,
0x70,0x65,0xdb,0x30,0x67,0xa1,0x13,0xe,0xa7,0x31,0xa8,0xe,0xbc,0x1e,0x22,0x7b,
0x59,0xa5,0x8f,0xf7,0x92,0x56,0x51,0xa0,0x27,0x44,0x51,0x29,0x97,0x25,0xba,0xb7,
0x7c,0x73,0x5d,0x7b,0xa8,0xce,0xeb,0x81,0x80,0x2,0x38,0x8b,0x5d,0xcf,0x2,0xf8,
0xfd,0x70,0x39,0x7d,0x9a,0xd,0x4b,0x57,0xc7,0xe8,0xd2,0x31,0xe7,0x55,0x88,0xd7,
0x43,0xfa,0x79,0xaf,0x72,0x4e,0x10,0x94,0x5a,0x49,0xa4,0x15,0xb2,0xa4,0xec,0x3d,
0xb4,0xa9,0xae,0x45,0x97,0xe,0x82,0x84,0xa6,0x0,0xce,0x62,0xd7,0x75,0x0,0x76,
0xf,0x97,0x1d,0x4e,0x23,0x8a,0x6f,0x8b,0x87,0xc5,0x6a,0x8,0xab,0x43,0x3c,0xa7,
0x28,0x5e,0xf,0x19,0xe0,0xbc,0x4a,0x9b,0x28,0x28,0x27,0x45,0x81,0x56,0xca,0x12,
0xdd,0x77,0x68,0x53,0xed,0xc9,0x70,0xf4,0xa7,0x2a,0x80,0xb3,0xd8,0x65,0x6,0x50,
0xb,0x20,0x67,0xb8,0x6e,0xf9,0x9a,0x58,0x4c,0xcd,0xb0,0x86,0xc3,0x87,0xa0,0x20,
0xa,0xa,0x65,0xdd,0x64,0x90,0xf3,0x2a,0xed,0x2,0xaf,0x34,0x48,0x22,0x3d,0x2c,
0x49,0xb4,0xe4,0xd0,0xc6,0xda,0xaf,0x43,0x69,0x57,0x4b,0x80,0x1b,0x0,0x7c,0x38,
0x42,0x62,0x80,0x9f,0xde,0x97,0x4,0x93,0x99,0x9,0xa5,0xaf,0xb0,0x40,0x12,0x29,
0x65,0xdd,0xc4,0xc3,0x79,0x49,0x87,0xc0,0x2b,0xd,0xa2,0x48,0xab,0x64,0x91,0x96,
0x12,0x42,0x2b,0x2b,0xb6,0xd4,0x29,0x63,0xfd,0x5e,0x4b,0x80,0x3f,0x2,0xf8,0xcb,
0x70,0x39,0x2a,0xc6,0x84,0xb5,0x77,0x26,0xe8,0xeb,0x79,0x98,0x21,0x4b,0x94,0xb2,
0x6e,0xe2,0xe5,0xbc,0x4a,0xa7,0xc0,0x2b,0x4d,0x5e,0xf,0xf9,0xe7,0xc1,0xa7,0x6a,
0x3f,0xfd,0x2e,0xcf,0xa4,0xf1,0xfb,0xd9,0x97,0x16,0x62,0x13,0xb4,0x68,0x93,0x17,
0x26,0x33,0xc3,0x44,0xc7,0x99,0x1c,0xd1,0x71,0xc8,0x2,0x90,0xd5,0xda,0xcc,0x9,
0x0,0xfc,0x4,0xd0,0x5a,0xd1,0x32,0x2e,0x2d,0x44,0xd8,0x83,0x7b,0xe5,0xfd,0x10,
0xa1,0x25,0x40,0x78,0x97,0xfa,0x49,0x84,0xff,0x9b,0x7,0xd5,0xc2,0x84,0x8,0x20,
0xa,0xa,0x6,0xfb,0x9,0x8c,0xb2,0x13,0x89,0xf6,0x34,0x44,0x5a,0xf4,0xd9,0x4c,
0xe9,0x81,0xb0,0xac,0x6e,0x94,0x52,0x9c,0x3d,0x25,0xe0,0x9b,0x33,0x2,0x32,0xa7,
0x4c,0xc3,0xed,0x45,0xb7,0xe2,0xf6,0x25,0xeb,0x60,0xb7,0xd8,0x47,0x38,0xac,0x38,
0x80,0xd6,0xfe,0x93,0xa8,0xef,0xae,0x42,0x59,0xeb,0xfb,0xe0,0x65,0x6f,0x38,0x5c,
0x19,0x13,0xba,0xb,0x30,0xd8,0x4f,0xf0,0xe5,0xe7,0xfd,0x30,0xc3,0x8a,0x17,0x1f,
0xdd,0x8a,0x6b,0xf3,0x56,0xab,0xf2,0x1c,0x96,0x68,0xcc,0x9a,0xb2,0x18,0xb3,0xa6,
0x2c,0xc6,0x9a,0x9c,0x7b,0xf1,0x69,0xf3,0xeb,0xd8,0xd7,0xfc,0x6,0x28,0xc6,0x3e,
0x9c,0xe9,0x9,0x5d,0x5,0x70,0xf7,0xcb,0x28,0xf9,0xa0,0x17,0xb1,0xd1,0x76,0x1c,
0x7e,0xe1,0x0,0xe2,0x9c,0xc1,0xed,0x1d,0xec,0x66,0x27,0x6e,0x99,0xf9,0x10,0xa6,
0xc7,0xe6,0x61,0xfb,0xb1,0xa7,0x20,0xc8,0x9c,0x3f,0x89,0x2,0x3b,0xff,0xdd,0x5,
0xa3,0x91,0xc1,0xb9,0x77,0x6b,0xd1,0xcf,0x77,0xa1,0x9f,0xeb,0xc6,0xa1,0xb3,0x1f,
0xa2,0xaa,0xbd,0xe4,0xb2,0x7d,0xd6,0x6d,0xd,0x90,0x25,0x8a,0xd2,0x4f,0xfa,0xc0,
0x30,0x6,0xec,0x79,0xee,0xfd,0xa0,0x1f,0xfe,0x52,0xcc,0x49,0x29,0xc2,0x3,0x57,
0x3d,0x3,0x6,0xfe,0x3b,0xce,0x81,0x3e,0x19,0xa2,0xa0,0x20,0x7b,0xda,0x54,0xd8,
0x4c,0x76,0x24,0x47,0x66,0x22,0x37,0x71,0x3e,0xd2,0xa3,0x73,0x54,0x5a,0xa,0x1e,
0xba,0x9,0x50,0xf7,0x35,0xb,0x76,0x90,0xe0,0x9e,0x1b,0x6e,0x40,0x76,0x92,0xb6,
0x53,0xcd,0x17,0x4e,0x62,0xc3,0xf6,0x47,0x50,0xd9,0x7c,0x48,0xd5,0x9e,0x97,0x74,
0x35,0x56,0x65,0xaf,0xf3,0xab,0xef,0xee,0x14,0x1,0x0,0xf3,0x73,0xe7,0xe8,0xe3,
0xf0,0x10,0x74,0x11,0xc0,0xcb,0x12,0x34,0x56,0xb3,0x88,0x8d,0x8d,0xc0,0xd3,0xeb,
0x9f,0xd5,0xe4,0x7d,0xd4,0xf0,0x12,0xfe,0x5e,0x79,0x2f,0x1a,0xdd,0x9f,0xa3,0x78,
0xc3,0x7a,0x2c,0xff,0xc3,0x72,0x28,0xd4,0x7f,0xbb,0x7e,0x7d,0xee,0x3,0xb0,0x9a,
0x22,0x46,0xd5,0x75,0x75,0xf8,0x4,0x58,0x3d,0x4f,0x7d,0x4d,0xb9,0x5c,0xe8,0x22,
0xc0,0xe9,0x7a,0xe,0x32,0xa1,0xb8,0xe5,0xda,0x55,0xb0,0x98,0xd4,0x4f,0x8c,0xd,
0x3d,0x47,0xf0,0x49,0xd3,0x6b,0x0,0x80,0xd4,0x4c,0x1b,0xf2,0xe6,0x3a,0x70,0xb4,
0xba,0x5,0x4f,0xbd,0xfd,0xa4,0x1f,0xd7,0x62,0xb4,0x61,0x6e,0xca,0x8a,0x51,0x75,
0xdd,0x9d,0x22,0xcc,0x66,0x6,0xab,0xa,0x7e,0xa2,0x87,0xcb,0x23,0xd0,0x45,0x80,
0x6f,0xce,0x8,0x0,0x80,0xfb,0x7f,0x7c,0xbf,0x26,0xe7,0x40,0xcb,0x7f,0x41,0x2f,
0xf9,0x6b,0x5f,0x59,0x10,0x89,0x8,0xbb,0x1,0xdb,0x76,0xee,0xc0,0x20,0x37,0xe0,
0xc7,0x5f,0x98,0xf6,0xed,0x83,0xb2,0x1e,0x2,0xd6,0xad,0x20,0x33,0x3d,0x11,0x66,
0xa3,0x59,0xf,0x97,0x47,0x10,0xb2,0x0,0x9e,0x1,0x19,0xfd,0xbd,0x12,0x52,0x92,
0x9d,0x98,0x95,0x9e,0xaf,0xc9,0x3b,0xd3,0x5b,0x33,0xaa,0x6c,0x34,0x2,0xf1,0x49,
0x66,0x8,0x3c,0x41,0x49,0xf5,0x1e,0x3f,0x7e,0x6e,0xe2,0x7c,0xb4,0xd4,0x58,0xf0,
0xee,0xcb,0x9d,0x58,0x99,0xfa,0x20,0x2a,0x5f,0xda,0x85,0x77,0xfe,0xf4,0x86,0x1f,
0x2f,0x23,0x26,0x17,0x8b,0xd2,0xd7,0x20,0x3f,0xb9,0x10,0x59,0x71,0xf9,0x70,0x5a,
0x63,0xc7,0xe5,0x7f,0xc8,0xaf,0xc1,0xee,0x4e,0x9,0x0,0x90,0x77,0x45,0xb6,0x26,
0xa7,0x97,0xeb,0x44,0x3f,0xef,0x1f,0x1b,0x8d,0x4f,0x34,0xa3,0xad,0x45,0xc0,0x81,
0xda,0x83,0xb8,0x75,0xd1,0x9d,0xa3,0x6c,0x6,0xc6,0x80,0xb5,0x57,0xad,0xc5,0x97,
0x15,0xff,0x82,0xd5,0x68,0xd3,0x14,0x77,0x46,0xe2,0x2,0xcc,0x48,0x5c,0x30,0x52,
0xde,0xdd,0xf8,0xa,0x76,0x35,0xbc,0x1c,0xb4,0xff,0x21,0x8f,0x0,0x8e,0x25,0x0,
0x80,0xe4,0xd8,0x29,0x9a,0x9c,0x33,0xbd,0xb5,0xaa,0xf5,0x71,0x53,0x7c,0xc3,0xf9,
0x78,0x53,0x9d,0xaa,0x7d,0xf9,0xec,0x15,0xaa,0xf5,0x7a,0x22,0x74,0x1,0xbc,0xbe,
0x79,0x9d,0x92,0x30,0x55,0x93,0x33,0x20,0x5c,0x54,0xad,0x8f,0x89,0xf5,0xd,0xc0,
0x73,0xe7,0x2f,0xa8,0xda,0x13,0xa3,0x92,0x42,0xf4,0x6e,0x6c,0x84,0x3c,0x5,0x86,
0x5,0xc8,0x48,0x4c,0xd3,0xe4,0x88,0x6a,0x3b,0x3b,0x0,0x16,0x8b,0x4f,0x7f,0x41,
0x90,0x55,0xed,0xd1,0x11,0x71,0x58,0x75,0x63,0x1c,0xb6,0xee,0xda,0x8a,0x67,0xde,
0xfc,0x7,0xde,0xfd,0xf3,0x7f,0x30,0x33,0x6d,0x54,0xac,0x6,0x8d,0x5d,0xc7,0xd1,
0xd8,0x75,0x1c,0x16,0xa3,0x15,0x76,0x6b,0x24,0xce,0xf,0x8e,0x2f,0xa8,0xac,0x9b,
0x0,0xae,0x84,0x4c,0x4d,0x8e,0x40,0xd4,0x5,0x30,0x9a,0x18,0x80,0x1,0x24,0x59,
0x3d,0x74,0x67,0x37,0x3b,0x91,0x9c,0x6a,0x47,0x7d,0x4d,0xf,0xda,0xce,0xf1,0x18,
0x60,0xfb,0xfd,0x38,0xad,0x3,0x35,0xf8,0xf8,0xf4,0xb6,0xf1,0x3b,0x3e,0x4,0x1d,
0xa6,0x80,0x6f,0xd,0xc8,0x4e,0xbe,0x42,0x93,0xa3,0x35,0x2,0xc0,0x0,0x26,0x93,
0x1,0xb2,0xa4,0x1d,0xbb,0x74,0x5a,0xc6,0xb7,0xaa,0x8f,0x17,0xa1,0xb,0xc0,0x29,
0x30,0x18,0x80,0xa9,0xf1,0xe9,0x9a,0x1c,0x81,0xf0,0x9a,0x36,0xb3,0x19,0x20,0x84,
0x42,0x22,0x92,0xaa,0xdd,0x69,0x8d,0xb,0xd5,0xc5,0x80,0x8,0x49,0x0,0x59,0xa2,
0x20,0x12,0x85,0xc3,0x61,0x81,0x81,0xd1,0x6e,0x4a,0x6b,0xa,0x0,0x43,0xd3,0x0,
0xc0,0x80,0xd7,0x7f,0x33,0x4,0x0,0x51,0xe3,0x7c,0xaf,0x8f,0x17,0x21,0x9,0x20,
0x49,0xbe,0xb3,0xbb,0xd9,0x1c,0x38,0x68,0x2a,0x6b,0xfc,0x75,0x1,0xdf,0x14,0x0,
0x0,0xf,0xaf,0x2e,0x80,0xc3,0x12,0x7d,0x99,0xde,0x5,0x87,0x90,0x4,0x18,0xbe,
0x26,0xe3,0x79,0xed,0x7,0x4,0x0,0x8b,0xc9,0xa6,0x69,0x23,0x8a,0x4f,0x44,0x87,
0xd5,0xa9,0x6a,0x17,0x3,0x4c,0x1f,0x3d,0x10,0x92,0x0,0x46,0x23,0x60,0x32,0x1b,
0xc0,0xf3,0xea,0xaf,0xb1,0x61,0x58,0x8d,0x1,0x4,0x18,0x1a,0x45,0x4e,0x5b,0x94,
0xaa,0x9d,0x15,0x7,0x2f,0xdf,0xc1,0x20,0x10,0xf2,0x22,0x68,0xb5,0x31,0x50,0x14,
0xa0,0xc7,0xad,0x9d,0x6,0x60,0x31,0x46,0x68,0xda,0x24,0x49,0x81,0xc1,0xc0,0xc0,
0x66,0x51,0x17,0x89,0x95,0x26,0xb9,0x0,0x36,0x9b,0xaf,0x89,0xf6,0xde,0x36,0x4d,
0xce,0x77,0xcf,0xf6,0x97,0x82,0xc8,0x14,0xc6,0x0,0x4b,0x88,0x77,0xd2,0x8f,0x80,
0x8,0x5f,0x13,0x1d,0x7d,0xda,0xf9,0xe,0x16,0xa3,0x7a,0x8c,0x40,0x51,0x7c,0xff,
0x4c,0x16,0x6d,0x37,0x26,0xfd,0x8,0xb0,0x5a,0x7d,0xaf,0xb1,0xce,0xbe,0xe,0x6d,
0x8e,0xc6,0x14,0x20,0xb2,0x6f,0xfe,0x9b,0x34,0x86,0x80,0xa4,0x88,0x90,0x88,0x10,
0xa2,0x87,0x81,0xa1,0xc3,0x1a,0xe0,0x73,0xfe,0x42,0xbf,0xfa,0x81,0x6,0x0,0xe2,
0xed,0x29,0xaa,0xf5,0x2,0xe7,0xdb,0x45,0x46,0xda,0xd5,0x47,0x48,0x1f,0xd7,0x15,
0xa2,0x77,0x63,0x23,0x64,0x1,0xe2,0x92,0x7c,0xc7,0x89,0xc3,0xf5,0x55,0x9a,0x9c,
0x8c,0x98,0x5c,0xd5,0xfa,0xde,0x1e,0xdf,0xdb,0x23,0x2b,0x5d,0xfd,0x20,0xd5,0xd4,
0x73,0x34,0x44,0xef,0xc6,0x46,0xc8,0x2,0xa4,0x66,0xd8,0x60,0x30,0x0,0x95,0xd5,
0xea,0x67,0x7a,0x0,0x88,0xb1,0x25,0xaa,0x46,0x6a,0x7a,0x7b,0x7c,0xfb,0x87,0x82,
0xec,0x59,0xaa,0xbf,0xab,0xef,0xfe,0x6a,0xcc,0xfe,0x99,0x0,0x3b,0xd0,0x60,0x10,
0xb2,0x0,0x66,0xb,0x83,0xa4,0x54,0x2b,0xdc,0x83,0x22,0xf6,0xd5,0xf8,0x87,0xb6,
0x86,0x91,0x11,0xed,0x3f,0xa,0xfa,0x86,0x46,0x40,0xe1,0xac,0xa5,0x7e,0x36,0xa,
0x8a,0x86,0xee,0x23,0xc3,0x85,0x91,0xba,0xef,0x22,0xc1,0x9e,0x7a,0x19,0x5e,0x7f,
0xb,0x5d,0x82,0xa2,0xa9,0x2e,0xdf,0x1c,0x7e,0x6b,0xff,0x5b,0x9a,0x9c,0xfc,0xe4,
0xc2,0x51,0x65,0x59,0xa2,0xe8,0xb9,0x20,0x22,0xc2,0x61,0xc4,0x8a,0xbc,0x95,0x7e,
0xfc,0xb6,0x81,0x26,0x78,0x44,0xdf,0xf1,0xd7,0x3c,0xb4,0xd0,0x76,0xd,0x76,0xfb,
0xf7,0x1d,0x35,0x1d,0x0,0x20,0x89,0x14,0x7d,0x17,0x65,0x18,0x88,0xdd,0x8f,0x13,
0x8,0xfa,0x8,0x90,0xe9,0x13,0xa0,0xec,0xeb,0x63,0x9a,0x9c,0x65,0x99,0x37,0x63,
0xaa,0x73,0xfa,0x48,0xf9,0xc4,0x51,0xf,0x24,0x91,0xe2,0xf1,0xf5,0xf7,0xc3,0x61,
0x8d,0xf4,0xe3,0x1f,0xef,0x38,0x38,0xf2,0xff,0xc8,0xa1,0x9c,0xc4,0xe6,0xf6,0x46,
0x3f,0x5e,0x52,0xa4,0xb,0xeb,0xae,0xdc,0x88,0x14,0x71,0x39,0x7e,0x57,0xb8,0x15,
0x8f,0xad,0x78,0x61,0x5c,0xbe,0xeb,0x22,0x80,0x23,0xd2,0x88,0xe4,0x54,0xb,0xba,
0xbb,0x59,0x7c,0x72,0x6c,0x97,0x7a,0x47,0x8c,0x11,0x77,0xcf,0x79,0x12,0x53,0x1c,
0x69,0x68,0xae,0xf3,0xe2,0x54,0x3d,0x87,0xd5,0xcb,0x7e,0x84,0x47,0x6f,0x7a,0xc2,
0x8f,0xdb,0xcd,0xb6,0x61,0xef,0xa9,0x6f,0x23,0xc0,0xce,0x68,0xdf,0x42,0xdb,0x70,
0xae,0x49,0xb5,0xed,0xa2,0xdc,0x62,0x3c,0xfd,0xb3,0xbf,0x61,0x51,0x4e,0xa1,0xea,
0xb5,0x5a,0x20,0xe8,0x76,0x35,0xb6,0xf8,0x9a,0x68,0xd8,0x22,0xc,0x78,0xe0,0xf9,
0xd,0xe8,0xea,0xef,0x54,0xe5,0x4c,0x8f,0x9b,0x8d,0x27,0x97,0xbd,0x85,0x9f,0x2f,
0xfa,0x2d,0x4e,0xbc,0x7a,0x10,0x3b,0x9f,0x78,0xcf,0x8f,0x43,0x41,0xf1,0xfa,0xf1,
0xa7,0x47,0xbd,0xff,0x33,0xb2,0x6c,0x70,0x38,0xd,0xd8,0x7d,0xb0,0x4c,0xf5,0xe,
0x21,0x14,0xe8,0x26,0x40,0x84,0xc3,0x88,0x25,0x2b,0x63,0x30,0x38,0x20,0xe2,0xfa,
0x4d,0xb7,0xa8,0x5e,0x79,0x1,0x40,0x84,0xc5,0x86,0x7b,0xae,0xb9,0xf,0xa9,0x1a,
0x1,0x94,0xb2,0xd6,0xf,0xd0,0xd4,0x33,0x7a,0x2a,0x19,0xc,0xc0,0xfc,0x65,0x31,
0x90,0x24,0x82,0x3b,0x9f,0xbb,0xb,0x5e,0xd1,0x3f,0x97,0x80,0x97,0x59,0x54,0x77,
0x1e,0xc4,0xfe,0x33,0xef,0x8c,0xcb,0x6f,0x5d,0xaf,0xc7,0x93,0x52,0x2d,0x28,0x58,
0x10,0x89,0xe3,0x87,0xdb,0xf1,0xd0,0x8b,0xf,0x62,0xdb,0x2f,0x83,0x8f,0xcf,0x53,
0x50,0x94,0x9f,0xfd,0x8,0x3b,0xeb,0xb6,0xaa,0xda,0xa7,0xa6,0x5b,0x70,0xdd,0x1d,
0x9,0x68,0x6b,0xf9,0x6,0xeb,0x5e,0x58,0x83,0xa2,0x82,0xa5,0xc8,0x9f,0x56,0x0,
0xaf,0xd4,0x87,0xfa,0xee,0x2a,0xb4,0xf4,0xd5,0x42,0xa1,0x64,0xdc,0x3e,0xeb,0x9e,
0x20,0x31,0x73,0xae,0x3,0x56,0x9b,0x1,0x3b,0xf6,0x7e,0x86,0xb,0x7d,0x37,0x61,
0xfb,0x23,0xaf,0x21,0xc6,0x1e,0x38,0xaa,0xd3,0xe1,0x6e,0xc1,0x9b,0xd5,0x7f,0xc5,
0xa9,0x8b,0xd5,0x1,0x79,0x76,0x87,0x11,0x39,0x79,0x76,0x0,0x1c,0x1a,0xd8,0x7d,
0x68,0xa8,0xdd,0x17,0xb2,0xbf,0x61,0x49,0x91,0xc9,0x9a,0x11,0x81,0xb4,0x69,0x56,
0xb4,0x9e,0x3a,0x8d,0x65,0x8f,0x17,0x21,0x37,0x3d,0x7,0xbf,0xb9,0xf1,0x61,0x14,
0xe6,0x16,0xf9,0x71,0xfb,0xb8,0xb,0xd8,0xf2,0xc5,0x7a,0x10,0x25,0x70,0x4c,0x21,
0x5c,0x8,0x5b,0x92,0x94,0xd5,0x66,0xc0,0x95,0x79,0x76,0xe4,0x2f,0xb4,0x60,0xcf,
0x17,0x55,0xf8,0xc5,0xf3,0xf,0xab,0xf2,0x62,0x23,0x92,0x90,0x19,0xa3,0xbe,0x13,
0xd4,0x15,0x1a,0xb9,0x37,0x61,0xcf,0x12,0x73,0x44,0x19,0x11,0x1b,0x6f,0xc2,0xf9,
0x8e,0x1,0x9c,0x6c,0x3b,0xa1,0xca,0x59,0x99,0x75,0x57,0xb8,0xdd,0x80,0x2c,0xd3,
0x33,0x6a,0xf5,0x13,0x92,0x26,0x97,0x36,0xcd,0x6,0x50,0xe0,0xd5,0x92,0x57,0x54,
0xed,0x73,0x53,0x8a,0xb0,0x61,0xc9,0x36,0xac,0xca,0xba,0x1b,0x57,0xc4,0xcf,0xb,
0x8b,0xf,0x92,0x44,0x55,0x53,0x52,0x26,0x44,0x0,0x57,0x56,0x4,0xc,0x6,0x60,
0x77,0x59,0xa9,0xea,0x5c,0x67,0x18,0x3,0x72,0x12,0xe6,0xe1,0xb6,0xbc,0x5f,0x63,
0x89,0x6b,0xad,0xee,0xfd,0x13,0x99,0x82,0xc8,0xb4,0x54,0xcd,0x36,0x21,0x2,0x44,
0xc5,0x1a,0x51,0xb0,0xc0,0x89,0xf3,0x1d,0x83,0xf8,0xd5,0x8b,0xf,0x4e,0x44,0x97,
0xa3,0xd0,0xd9,0x2e,0xd6,0x94,0x6f,0xae,0x53,0xd,0x2d,0x4d,0x58,0xaa,0xec,0x8c,
0x2,0x7,0x52,0x5d,0x56,0xbc,0xf3,0xf1,0x7e,0xec,0xa8,0xd0,0x3e,0x34,0xe9,0xd,
0xaa,0x0,0x3,0xbd,0xf2,0x43,0x5a,0xf6,0x89,0xcb,0x83,0x67,0x80,0xa2,0xe2,0x58,
0xb4,0xb7,0xf2,0xd8,0xf4,0xf6,0x66,0x7c,0x58,0xf5,0x1e,0x16,0x66,0x2f,0xc1,0xe2,
0xdc,0xc5,0xc8,0x4d,0xcb,0x5,0x2f,0xb3,0xe8,0xe3,0xba,0x70,0xfa,0x62,0xcd,0xd8,
0x6d,0x8d,0x3,0x2d,0xcd,0xdc,0x1b,0x65,0x1b,0x6b,0xd5,0x53,0xd2,0xa0,0xfd,0xc1,
0x44,0x25,0x80,0x85,0xc3,0xe5,0xdc,0x7c,0x7,0xe6,0x5d,0xad,0x7e,0x71,0x31,0x59,
0xa1,0x28,0x14,0x67,0x4f,0xf1,0x3b,0xf6,0x3d,0x56,0x73,0x47,0x20,0xde,0xf,0xef,
0x4b,0x88,0x0,0x90,0x25,0x4a,0x3d,0x6e,0xc2,0xe,0xf6,0xc9,0x47,0xdc,0x3,0xe4,
0xe1,0x43,0x9b,0x6a,0xd5,0x53,0x53,0x2e,0xc1,0xf,0x52,0x0,0x59,0xa6,0x60,0x7,
0x9,0xeb,0xf5,0x92,0xe,0x81,0xa3,0xd,0x92,0xa8,0x7c,0x25,0x89,0xb4,0xa4,0x6c,
0x63,0x6d,0xe5,0x78,0xdb,0x9a,0xd4,0x2,0x10,0x99,0xc2,0xe3,0x26,0x5e,0x8e,0x55,
0x3a,0x4,0x5e,0x69,0x14,0x5,0xa5,0x4a,0x12,0xe9,0x67,0x84,0xd0,0x8a,0x60,0x3e,
0x88,0xa,0x6,0x5a,0x2,0x4c,0x68,0xca,0x36,0x21,0x14,0x9e,0x41,0xc2,0x71,0xac,
0xef,0x3,0x27,0x51,0x50,0xaa,0x24,0x89,0x7e,0x46,0x64,0x5a,0x5e,0xb1,0xa5,0x2e,
0xac,0x87,0x4,0x2d,0x1,0xfe,0x8,0xdf,0x67,0x73,0xfe,0xb1,0xaa,0x10,0xa0,0x10,
0xa,0x8f,0x9b,0xf0,0x1c,0xab,0x74,0xf2,0x9c,0xd2,0x2c,0x8a,0xca,0x11,0x49,0xa4,
0xfb,0x89,0x4c,0xf,0x84,0xfb,0x41,0xb5,0xa0,0x2a,0x80,0x7b,0xcf,0xd9,0x52,0x67,
0xb1,0xeb,0x1a,0x0,0x7b,0x0,0xc4,0x8f,0xb7,0x51,0x45,0xa1,0x60,0xdd,0x84,0xf7,
0xb2,0x4a,0x97,0xc0,0x29,0xa7,0x44,0x41,0x39,0x2a,0x89,0xb4,0x54,0x96,0x69,0x69,
0xc5,0x96,0x3a,0x31,0x54,0xa7,0xf5,0x84,0xe6,0x1a,0xe0,0xde,0x73,0xb6,0xca,0x59,
0xec,0x5a,0xa,0xa0,0x4,0x80,0x6a,0xec,0x59,0x51,0x0,0xd6,0x4d,0x4,0x8e,0x25,
0xdd,0xfc,0xf0,0x83,0x4a,0xf4,0x73,0x59,0xa2,0xfb,0x2b,0xb6,0xd4,0x85,0xf7,0x62,
0x5f,0x27,0x4,0xf3,0xf5,0xb8,0x6b,0xe6,0x1c,0x47,0x65,0xf6,0x4c,0x7b,0x9c,0xd7,
0x43,0xba,0x79,0x5e,0x39,0x2d,0xa,0xca,0x31,0x49,0xa4,0x5f,0xc8,0x32,0x2d,0xa9,
0xd8,0x5c,0xf7,0xfd,0x7c,0xeb,0xa2,0x13,0xfe,0x7,0x6a,0x59,0x8e,0x78,0x3b,0xce,
0xc8,0xd8,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82,
};
static const unsigned char qt_resource_name[] = {
// QtWidgetsApplication1
0x0,0x15,
0x1,0x6d,0xd9,0xd1,
0x0,0x51,
0x0,0x74,0x0,0x57,0x0,0x69,0x0,0x64,0x0,0x67,0x0,0x65,0x0,0x74,0x0,0x73,0x0,0x41,0x0,0x70,0x0,0x70,0x0,0x6c,0x0,0x69,0x0,0x63,0x0,0x61,0x0,0x74,
0x0,0x69,0x0,0x6f,0x0,0x6e,0x0,0x31,
// src
0x0,0x3,
0x0,0x0,0x7a,0x83,
0x0,0x73,
0x0,0x72,0x0,0x63,
// qt.png
0x0,0x6,
0x7,0x87,0x57,0x47,
0x0,0x71,
0x0,0x74,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67,
};
static const unsigned char qt_resource_struct[] = {
// :
0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
// :/QtWidgetsApplication1
0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x2,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
// :/QtWidgetsApplication1/src
0x0,0x0,0x0,0x30,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x3,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
// :/QtWidgetsApplication1/src/qt.png
0x0,0x0,0x0,0x3c,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0,
0x0,0x0,0x1,0x7d,0x27,0x7a,0x82,0x80,
};
#ifdef QT_NAMESPACE
# define QT_RCC_PREPEND_NAMESPACE(name) ::QT_NAMESPACE::name
# define QT_RCC_MANGLE_NAMESPACE0(x) x
# define QT_RCC_MANGLE_NAMESPACE1(a, b) a##_##b
# define QT_RCC_MANGLE_NAMESPACE2(a, b) QT_RCC_MANGLE_NAMESPACE1(a,b)
# define QT_RCC_MANGLE_NAMESPACE(name) QT_RCC_MANGLE_NAMESPACE2( \
QT_RCC_MANGLE_NAMESPACE0(name), QT_RCC_MANGLE_NAMESPACE0(QT_NAMESPACE))
#else
# define QT_RCC_PREPEND_NAMESPACE(name) name
# define QT_RCC_MANGLE_NAMESPACE(name) name
#endif
#ifdef QT_NAMESPACE
namespace QT_NAMESPACE {
#endif
bool qRegisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *);
bool qUnregisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *);
#ifdef QT_NAMESPACE
}
#endif
int QT_RCC_MANGLE_NAMESPACE(qInitResources_QtWidgetsApplication1)();
int QT_RCC_MANGLE_NAMESPACE(qInitResources_QtWidgetsApplication1)()
{
QT_RCC_PREPEND_NAMESPACE(qRegisterResourceData)
(0x2, qt_resource_struct, qt_resource_name, qt_resource_data);
return 1;
}
int QT_RCC_MANGLE_NAMESPACE(qCleanupResources_QtWidgetsApplication1)();
int QT_RCC_MANGLE_NAMESPACE(qCleanupResources_QtWidgetsApplication1)()
{
QT_RCC_PREPEND_NAMESPACE(qUnregisterResourceData)
(0x2, qt_resource_struct, qt_resource_name, qt_resource_data);
return 1;
}
namespace {
struct initializer {
initializer() { QT_RCC_MANGLE_NAMESPACE(qInitResources_QtWidgetsApplication1)(); }
~initializer() { QT_RCC_MANGLE_NAMESPACE(qCleanupResources_QtWidgetsApplication1)(); }
} dummy;
}
添加到.qrc
的資源被轉(zhuǎn)成了16進(jìn)制數(shù)組。關(guān)于Qt的rcc,簡單介紹下,
rcc工具主要用于處理資源文件,可以將資源文件(如圖片、音頻、視頻等)打包成二進(jìn)制文件(*.rcc
),以便于在程序中加載和使用。rcc工具主要有以下兩種用途:
- 生成獨(dú)立的二進(jìn)制資源文件:對于較大的資源文件,不適合直接集成到目標(biāo)程序內(nèi)部,可以將其放到操作系統(tǒng)文件路徑,或單獨(dú)編譯成外掛資源文件(
*.rcc
)。rcc工具可以將資源文件壓縮打包,生成一個二進(jìn)制的*.rcc
文件,其中包含了所有的資源文件。這樣,在程序發(fā)布時,只需要帶一個*.rcc
文件即可,而不必帶一堆亂七八糟的碎文件。 - 應(yīng)用程序內(nèi)嵌資源:可以將資源文件編譯到應(yīng)用程序內(nèi)部,作為內(nèi)嵌資源。這在需要頻繁使用某些資源文件時可以提高程序的啟動速度和運(yùn)行效率。在Qt應(yīng)用程序中,可以通過包含相應(yīng)的
*.rcc
文件來訪問內(nèi)嵌資源。
因此,一般將.qrc
添加到項(xiàng)目中編譯、鏈接進(jìn)exe只是rcc的一種用法,即應(yīng)用程序內(nèi)嵌資源。而應(yīng)用程序內(nèi)嵌資源通常會使得exe本身體積增大,對于有些較大且非經(jīng)常使用到的的資源則不太合適。接下來介紹下如何生成獨(dú)立的二進(jìn)制資源文件。
3、外掛資源
利用rcc工具,將.qrc
單獨(dú)編譯成外掛資源文件(*.rcc
),可以把資源從exe剝離出來,方便替換而不用編譯代碼。
rcc工具具體指Qt提供的一個程序rcc.exe,比如本文所用Qt5.12.12在如下目錄:
實(shí)現(xiàn)方式也簡單,只需要把xxx.qrc文件編譯成xxx.rcc文件,然后在程序啟動時加載.rcc
文件,后面的調(diào)用方式便和第一種方式一樣了,具體命令如下:
rcc --binary resource.qrc -o resource.rcc
加載rcc:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
if(QResource::registerResource( R"(E:/work src/test/QtWidgetsApplication1/resource.rcc)") == true)
{
qDebug()<<"it's ok";
}
else
{
qDebug()<<"it's not ok";
}
MainWindow w;
w.show();
return a.exec();
}
小結(jié)下,使用.rcc
文件的優(yōu)點(diǎn)如下:
- 節(jié)省內(nèi)存空間;
- 改變資源時,不需要再次編譯程序,只需將舊的
.rcc
文件替換即可。
使用.rcc
文件的步驟如下:
-
生成
.qrc
文件; -
將
.qrc
及其所包括所有資源, 和 rcc.exe放在同一個目錄下,或?qū)cc.exe配置到環(huán)境變量; -
使用下述命令,根據(jù)
.qrc
文件生成.rcc
文件:rcc --binary resource.qrc -o resource.rcc
-
程序中添加
QResource::registerResource()
加載.rcc
文件。
在不需要的時候使用QResource::unregisterResource()
來進(jìn)行注銷,其余即像使用.qrc
那樣使用了。所以,我們可以把某業(yè)務(wù)的資源統(tǒng)一由指定的.qrc
管理,加載資源前先加載.qrc
。
有了resource.rcc后,圖標(biāo)資源就可以不需要了,因?yàn)槎家呀?jīng)編進(jìn)里面了。
另外,可以通過QResource::unregisterResource
從程序中卸載.rcc
文件。不過,如果程序已經(jīng)加載了圖標(biāo)資源,那么此時卸載.rcc
并不會影響已加載的圖標(biāo),而只會導(dǎo)致后續(xù)加載圖標(biāo)失效。
同理,如果程序中使用圖標(biāo)資源是在加載對應(yīng).rcc
之前,圖標(biāo)加載也不會因?yàn)?code>QResource::unregisterResource()而立即生效。不過,如果是通過樣式表(qss)來設(shè)置圖標(biāo)的,可以使用下面的方法來立即刷新,
ui.label->setStyleSheet(ui.label->styleSheet());
style()->polish(ui.label);
五、小結(jié)
通過本文前序章節(jié)的介紹,我們已經(jīng)走通了QUiLoader加載.ui、插件(自定義控件)、外掛資源文件。為方便管理,我們可以修改插件項(xiàng)目輸出路徑,保證.ui、.dll、.rcc處于同一目錄下:文章來源:http://www.zghlxwxcb.cn/news/detail-771527.html
完全加載代碼如下:文章來源地址http://www.zghlxwxcb.cn/news/detail-771527.html
QtWidgetsApplication1::QtWidgetsApplication1(QWidget *parent)
: QMainWindow(parent)
{
const QString runtimeUIPath = R"(E:/work src/test/QtWidgetsApplication1/src_runtime/)";
QResource::registerResource(runtimeUIPath + "resource.rcc");
QUiLoader loader;
loader.addPluginPath(runtimeUIPath);
QFile file(runtimeUIPath + "Widget.ui");
file.open(QFile::ReadOnly);
QWidget *myWidget = loader.load(&file, this);
file.close();
auto *layout = new QVBoxLayout;
layout->addWidget(myWidget);
ui.setupUi(this);
ui.centralWidget->setLayout(layout);
}
到了這里,關(guān)于Qt、C++動態(tài)UI的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!