這次想要改用 MenuBar 的方式來取代 TextButton
但沒想到這個工程十分大,整個 file structure 都改了
但整體來說也比較彈性一點
1. 首先,修改 Introjucer 自動產生的 Main.cpp
新增加一個 MainWindow.h ,並把 Main.cpp 裡面的 class MainWindow 一整個挖過來
並做一些適當的修改
當然相對應也要增加 MainWindow.cpp 來實作 member functions
詳細的 code 這邊不贅述,講幾個為了 menu bar 要特別加的部分
[1] 這邊繼承 AsyncUpdater 這個 class,所以必須實作 handleAsyncUpdate()
而為什麼要繼承 AsyncUpdater,主因是看到 JuceDemo 這個 example 裡面有使用
想來使用看看,不使用這個 class 也是可以達到想要做的事
AsyncUpdater 簡單就是說可以用 callback 的方式來做一些事情
而這個 callback 呼叫時間是 async 的,也就是會晚一點才會被呼叫
詳細 API 說明可以看這裡
[2] 這邊為了 Menu Bar 這個 feature,新增加了兩個 static member functions
[3] 為了讓之後 Menu Bar 可以指定相對應的行為,必須透過 CommandIDs 來指定
2. 來看一下 getApplicationCommandManager() 這個 static function 的實作
可以看到,這個 function 主要是回傳 applicationCommandManager 實體出去
Menu Bar 選單上要能執行的功能
就是會透過 applicationCommandManager 來註冊
而為什麼要特地寫一個 static member function 來做這件事
主要是因為想要一個統一的 ApplicationCommandManager 來管理就好
因此 applicationCommandManager 本身也只是 MainWindow.cpp 裡面的一個 static 變數
3. 接著來看 MainWindow 的 constructor
[1] 這個是要能讓 Menu Bar 上的功能,也可以有快捷鍵的功能
快捷鍵的設定之後會再說明
[2] 因為 MainWindow 有繼承 AsyncUpdater
要使用到 AsyncUpdater 的功能,就要呼叫 triggerAsyncUpdate()
4. 來看一下 handleAsyncUpdate()
這邊做的是主要就是註冊 Menu Bar 會用到的功能
而可以看到這邊註冊了兩次
因為之後 Menu Bar 的功能,有對 mainContentComponent 的,也有對 Application 本身
明確的來說,一個是開啟圖檔功能,一個是關閉程式功能
5. 接著來看 MainComponent.h
[1] 為了要有 Menu Bar 這項功能,會使用 MenuBarComponent 這個 component
而 MenuBarComponent 必須用一個 MenuBarModel 來初始化
因此讓 class MainContentComponent 繼承 MenuBarModel
[2] 因為 class MainContentComponent 要可以被 ApplicationCommandManager 拿來註冊
它就必須繼承 ApplicationCommandTarget (因此可以推測JUCEApplication 也有繼承)
因為繼承 MenuBarModel,所以必須實作以下的 function
因為繼承 ApplicationCommandTarget ,所以必須實作以下的 function
menuBar 就是所要使用的 MenuBarComponent
而在初始的時候,因為 MainContentComponent 已經繼承了 MenuBarModel
所以直接傳入 this
7. 接著來看因為繼承 MenuBarModel 所必須實做的三個 functions
getMenuBarNames() 是要設定 Menu Bar 上所要顯示的欄位名字
這次只要一個開啟圖檔功能就好,所以用一個 Files 欄位
getMenuForIndex 是當選到 Menu Bar 上某個欄位時,要顯示哪些功能
首先可以看到,當 menuIndex 為 0 時,是選到 Files 欄位
也就是在 getMenuBarNames() 所定義的 array 順序
而選到 Files 欄位時,因為除了顯示功能之外,還要能有相對應的功能
所以這邊使用 addCommandItem() 來增加功能
可以看到 commandManager 被當作參數傳入
以及之前在 class MainWindow 所定義的 CommandIDs 也拿來用
另外在前面也有提過,除了開啟圖檔功能之外,還會有一個關閉程式的功能
在這邊直接使用 StandardApplicationCommandIDs::quit,不用另外定義
而 addSeparator() 就是增加一個區隔線
可以在 menuItemSelected() 來處理一些較特殊的功能
但一般來說,都會用 addCommandItem() 的方式處理
8. 來看因為繼承 ApplicationCommandTarget 所必須實做的四個 functions
getNextCommandTarget() 基本就這樣寫,不用動
在 getAllCommands(),把會用到的 CommandIDs 都附上
getCommandInfo() 設定功能要顯示出來的名稱、簡短說明、分類
並且設定快捷鍵,這邊就是將 ctrl+o 當作開啟圖檔的快捷鍵
perform() 就是當 Menu Bar 提供的功能被選擇時,所要執行相對應動作的地方
可以看到,是用 CommadIDs 來做辨識
這邊還需要多實作一個開啟圖檔的功能 => openImageFile()
9. openImageFile() 其實沒什麼特別,就是上一版實做的開檔功能
只是上一版是用 TextButton 來做,這次用 Menu Bar
所以變成一個單獨的 function 就好
10. 結果
沒有留言:
張貼留言