close

根據不同的平台作不同的處理,首先先以Mac OS X為範例

啟稿: 2014/12/24

完稿: 2014/12/30

 

QT CueTai線索台

QT跨平台實作03-跨平台實作進階:採用外部資源檔,OSX下之實例

 

上次提到若現在希望使用者可以自行放入想要的音效檔,那似乎不能使用QT內建資源檔這種方法,而必須根據不同的平台建立相對的外部資源目錄來放置音效檔,所以我們要根據不同的平台作不同的處理,首先先以Mac OS X為範例。

 

l  Mac OS Xapp封裝結構

我們可以參考在Mac OS X下的應用程式它的整包package是如何的結構,在此以Eclipse.app為例:

 03-01  

 

Mac OS X下所看到的*.app執行程式,其實是一個封裝的package,如下Eclipse.app兩指點選(如同Windows作業系統是按右鍵)會出現隱藏式選單如下:

 03-02

 

選取顯示套件內容就會出現封裝的路徑結構,在Resources/下可以看到該程式整併進來的外部檔案

 03-03

 

而真正的執行程式是放在MacOS/下如下圖:

 03-04

 

l   QT下建置Mac OS X封裝結構

同樣的,我們可以檢查原來我們在前一次所建置出來的analogclock.app,你可以發現在Resources/下並沒有任何的檔案,因為我們原來的音效檔與圖示檔都整併在執行檔中,並不會出現在此目錄中;現在我們有可以利用QT的專案巨集命令來建置Mac OS X封裝結構。

有關QT如何將所需要的資源檔在建置時封裝成Mac OS X app結構,這方面的訊息在網路上不容易Google得到,一開始連關鍵字該如何描述都很頭大;這個需求在建置deployment時可能會需要,所以用"deployment" keyword來試著得到你要的資訊;在QT說明畫面的搜尋欄位輸入keyword "Mac deployment" ,可以參考QT for Mac OS X - Deployment說明如下:

 03-05

這一篇是相當豐富而有用的資料,它不只提到架構,打包,連靜態連接及最後封裝發佈都涵蓋了!有關他的簡體中文翻譯版在2011就有人翻譯了!網路上可以輸入"Mac发布Qt应用程序"應該找得到!只是這篇對於初學者來說相當艱深,也超出我們現在的需求,但不可否認的,最後我們一定會用到;現在我們可以現專注在本文前段有關架構與打包,文中有提到打包的keyword "Bundle",但該如何用卻沒有進一步的資訊;不過我們可以在搜尋欄位再輸入keyword "Mac Bundle" 找看看,前面都是剛才搜尋過的,但在"Variables | QMake"可以看到Bundle有用的巨集命令QMAKE_BUNDLE_DATA如下

 03-06

 

在一開宗明義就很明顯加注解"Note: This variable is used on Mac OS X only.",這些巨集變數定義在Qmake,也就是QT的專案管理*.pro檔可以增加的命令;看說明中的範例如下:

FRAMEWORK_HEADERS.version = Versions

FRAMEWORK_HEADERS.files = path/to/header_one.h path/to/header_two.h

FRAMEWORK_HEADERS.path = Headers

QMAKE_BUNDLE_DATA += FRAMEWORK_HEADERS

 

若要用在我們的範例上,可以在analogclock.pro加入如下的巨集:

ResourcesFiles.files=\

        ../analogclock/audio/alarm.wav\

        ../analogclock/audio/bird.wav\

        ../analogclock/audio/cricketnight.wav\

        ../analogclock/audio/dolphin.wav\

        ../analogclock/audio/hour.wav\

        ../analogclock/audio/laser.wav\

        ../analogclock/audio/water.wav

 

ResourcesFiles.path=Contents/Resources

QMAKE_BUNDLE_DATA+=ResourcesFiles

 

ResourcesFiles是我們自行定義的巨集變數,而其中內含的資源檔在此建議都採用相對路徑,不然在跨到另外的平台會出問題;特別注意的是Qmake當時所認知的路徑在哪裡呢?答案就在專案頁次裡的建置目錄下的設定,以我的例子來說明:我的建置目錄如下:

          /Users/apple/Documents/QtWork/build-analogclock-Desktop_Qt_5_3_0_clang_64bit-Release

而我的資源檔放在source code下的目錄:

          /Users/apple/Documents/QtWork/analogclock/audio

所以相對路徑表示我們就必須加上"../analogclock/audio/"

 

l   修改程式

現在資源檔就會在建置時打包到目錄下,所以我們在程式中取用的時候就該寫成以下的形式:

    soundQuarter=newQSound("Resources/alarm.wav");

但問題來了!程式在執行時所在目錄位置到底在哪兒?這方面資訊也不多,各位可以寫個小程式來dump出來current path,你就會發現在QT開發平台debug/release執行時與建置後正式執行app所在目錄位置是完全不一樣的,為了程式的一致性,我們必須在原始碼中判斷目前的狀態來配合不同的狀態下執行時所在目錄位置;因此我們在analogclock.h此引進了底下的變數來記錄相對與絕對路徑:

    //-OPMode

    enumOP_MODE_{APP_=1,DEBUG_,RELEASE_,OP_Count_};

    intOpNow;

    //-Path

    QDirD_Current;

    QStringS_ResPath;                  //OSresourcepath(dependondifferentOS)

    QStringS_CurrentPath;              //currentPath()returnpath

    QStringS_AbsPath;                  //FinalAbsolutivepath.

程式一開始執行時就要知道目前是在何種狀況,來改變執行時所在目錄位置,我們用OpNow來知道是在開發平台debug/release狀態下,還是建置後正式執行app;所以程式一開始改成如下:

    clock.D_Current=QDir::current();

    if(clock.OpNow==clock.APP_)

            clock.S_CurrentPath=clock.D_Current.path()+"/analogclock.app/Contents/";

    //Debug/ReleaseDevelopmentMode

    else{

            clock.D_Current.cdUp();

            clock.S_CurrentPath=clock.D_Current.path()+"/";

    }

    clock.S_ResPath="Resources/";

一開始判斷若目前是建置後正式執行app,那程式在執行時所在目錄位置就在analogclock.app所在位置,因此我們就要將降到Contents/該層;若我們現在是在QT開發平台debug/release狀態下,那程式在執行時所在目錄位置就在analogclock.app/Contents/MacOS/該層,所以我們就要升上一層,如此就都一致;若要取資源檔,都是往Resources/目錄下取檔案即可!如下用法:

        soundQuarter=newQSound(S_ResPath+"alarm.wav");

 

l   建置與執行

在在QT開發平台debug/release狀態下,記得最前端加入以下一行程式:

    clock.OpNow=clock.DEBUG_;                     //APP_,DEBUG_,RELEASE_

要建置正式執行app則改為:

    clock.OpNow=clock.APP_;                       //APP_,DEBUG_,RELEASE_

如此就大功告成,檢查一下建置的,真的在Resources/目錄下放置所有的檔案

 03-07

 

Note: 若執行時沒有聲音,就表示路徑不對了!

 

l  延伸應用及問題

是否其他平台也一樣呢?

 

arrow
arrow
    全站熱搜

    Philip4G 發表在 痞客邦 留言(1) 人氣()