1. 程式人生 > >Qt那些事0.0.18

Qt那些事0.0.18

開發十年,就只剩下這套架構體系了! >>>   

今天要記一下Qt中的Resource。自我感覺理解的不錯,但是還會難免有謬誤,在日後有可能會更新,也有可能不會。

小聲的唸叨一句,女人心,海底針。

今天就直接跳過了關於QML在qrc檔案中的介紹,那一部分前一段時間吃的比較透,本來洋洋灑灑寫了一個doc介紹,但是轉眼就找不到了,甚是懊惱,所以索性就不打算記錄了。也許哪天又想了呢?變化無常,男人也可以,對吧。

Qt如今(目前Qt5.12)支援資原始檔,預設情況下是可以編譯進exe檔案和dll檔案中,而且這是預設的形式。根據官方文件(The Qt Resource System)中介紹。在介紹資源之前,還是要先說一下資源路徑問題。

qrc檔案的例子就直接使用以上官網中的例子,再稍微改動一些。

<!DOCTYPE RCC>
<RCC version="1.0">
    <qresource> 
        <file>images/copy.png</file>
    </qresource> 
    <qresource prefix="/myres">
        <file alias="cut-img.png">images/cut.png</file>
        <file alias="icon/save.png">images/save.png</file>
    </qresource>
</RCC>

以上列子中在RCC下存在兩個節點,一個使用了prefix屬性,另一個是沒有。存放資源的路徑是取決於qrc檔案中定義的prefix,以及每一個檔案中對應的alias。這是Qt資原始檔系統的基本方式。例如訪問copy.png則需要使用路徑images/copy.png,而使用cut.png時需要使用myres/cut-img.png,save.png更是要兩個部分結合,myres/icon/save.png。

取檔案有兩種協議方式:

  1. 以File方式讀取檔案。這種方式是以 “:” 為字首;
  2. 以QUrl方式讀取檔案。這個是需要使用“qrc:”為字首;

至於以哪種方式獲取資源,則是取決於具體的內容和方式了。如要讀取其中的一個檔案,則使用第一種,第二種方式是獲取不到檔案的。而在QML中載入資源,如Image,因為原本定義就是需要QUrl,則只能是第二種了,如其source的屬性定義就是使用url:

source : url

Image can handle any image format supported by Qt, loaded from any URL scheme supported by Qt.

The URL may be absolute, or relative to the URL of the component.

資源的兩種方式:

  1. 嵌入到程式當中
  2. 以額外檔案的方式

其中(1)是以預設方式來處理,這裡就不贅述。主要按照文件介紹(2)。 Qt支援資原始檔的動態載入,實現起來也很簡單。首先是正常編輯qrc檔案,可以先按照預設方式在pro中處理,待程式不存在其他問題之後,在pro中取消掉對此qrc的依賴。然後,通過rcc程式,將資源打包成單獨的rcc檔案(其實拓展名也無所謂,只是大家喜歡統一一下)。 常用的命令就是

rcc.exe --binary -o res.rcc res.qrc

這時會生成資原始檔。可以放到釋出檔案中,在軟體中需要提前註冊此資源,方便其掛載到記憶體樹中(這麼解釋的,沒深入瞭解)。

引入QResource檔案,然後呼叫其靜態方法

QResource::registerResource(qApp()->applicationDirPath()+"\res.rcc");

此處要使用絕對路徑,同時最好也要進行載入判斷,即返回值表達是否載入成功。 成功之後,程式中就會像內嵌了資原始檔一般進行資源訪問了。

這種方法的主要問題

文字檔案隱藏的不夠友好。

通過rcc無論使不使用--compress開關,生成的資原始檔照樣可以通過記事本(習慣notepad++)開啟,頂多修改下編碼格式,文字檔案的內容原封不動的儲存在資源中(甚至連換行符\r\n都在),真的不知道是不是我的zlib找不到所致。

目前還沒有找到其他較好的方法,想到的只有在自己釋出的時候使用加密/加壓後的檔案,在使用時候先解密/解壓到臨時檔案,然後使用QResource載入此臨時檔案。

對於二進位制檔案,如圖片等,這些倒是一點不用擔心。

原文件還介紹了將qrc嵌入到DLL的方法,需要強制使用 Q_INIT_RESOURCE() 方法註冊該qrc檔案。如果還想在DLL檔案外部使用此資源,在呼叫此資源前也要使用Q_INIT_RESOURCE方法。沒有測試,不做介紹。

學了點Markdown,感