Outlet 及 Action

Outlnet 及 Action 是連結使用者介面及程式碼的關鍵. 這裡製作一個顯示時間的程式, 以示範 Gorm 中, outlet 及 action 的使用, 以及控制者 (controller) 及使用者介面 (view) 的關係.

圖形 12.1. Simple TimeMachine

Simple TimeMachine

執行 Gorm, 選 "Document->New Application", 並加入一個字串 (Title) 及按鈕 (Button).

圖形 12.2. Interface of simple TimeMachine

Interface of simple TimeMachine

使用 Inspector 改變按鈕及視窗的內容.

圖形 12.3. Change title of button

Change title of button
Change title of button

這是所有使用者介面的部份了.

接下來要製做控制者物件, 來處理使用者介面的動作及改變. 在主視窗中選 "Classes".

圖形 12.4. Classes in Gorm

Classes in Gorm

這裡會列出所有可使用的物件 (類別). 在這裡, 控制者不需要特別的功能, 直接繼承自 NSObject 即可. 選 NSObject, 選 "Classes->Create Subclass" 產生新類別.

圖形 12.5. Create subclass of NSObject

Create subclass of NSObject

在新類別上點兩下, 修改名稱為 Controller.

圖形 12.6. Change class name

Change class name

接著要在 Controller 中加入一個 outlet 及一個 action. Outlet 要連到視窗上的字串, 以便控制其內容, action 則要連到按鈕上, 當使用者按下按鈕時, 便會觸動這個 action.

選 "Controller" 類別, 並在 Inspector 中選 Outlets 面版. 選 "Add" 按鈕, 在產生的 outlet 上點兩下修改名稱為 "label". "Controller" 類別的 outlet 便增加為一. 點一下 outlet 的小圓圈可以列出所有的 outlets 來.

圖形 12.7. Add outlet

Add outlet

同樣的方法在 Actions 面版上增加一個 "showCurrentTime:". 要注意最後的冒號, 這會在接下來的文章中說明.

圖形 12.8. Add action

Add action
Add action

類別設計好了, 就可以產生新的物件出來. 選 "Controller" 類別, 選 "Classes->Instantiate". 在主視窗的 Objects 中, 可以看到新產生的物件, 稱為 Controller. 有了實際的物件, 便可以與使用者介面相連接了.

圖形 12.9. NSOwner

NSOwner

首先先連接 outlet. 按住 Ctrl 鍵, 選 Controller 物件, 拖拉到視窗上的字串. Controller 上應有個綠色的 "S", 表示來源 (Source), 而字串上應有紅色的 "T", 表示目標 (Target). 接著在 Inspector 中, 選擇 Controller 要使用的 outlet, 目前只有 label. 選 "Connect" 按鈕, 即可連結這個 outlet.

圖形 12.10. Connect outlet

Connect outlet
Connect outlet
Connect outlet

接著連結 action. 按住 Ctrl 鍵, 選 "Get Current Time" 按鈕, 拖拉到 Controller 物件. 在 Inspector 中選 target, 指的是 Controller 物件. 這時會列出 Controller 中所有的 actions. 選 showCurrentTime:, 按 "Connect" 連接兩者.

圖形 12.11. Connect action

Connect action
Connect action
Connect action

最後, 要產生 Controller 的程式碼. 在主視窗選 Controller 類別 (不是物件), 選 "Classes->Create Class Files", 存檔面版會出現, 內定的檔名為 Controller.m 及 Controller.h. 選 "O.K." 即可. 最後將這個 Gorm 存檔成 TimeMachine.gorm.

到目前為止, 有一個 TimeMachine.gorm 目錄及 Controller.h, Controller.m 兩個檔案:

Controller.h:

/* All Rights reserved */

#import <AppKit/AppKit.h>

@interface Controller : NSObject
{
   id label;
}
- (void) showCurrentTime: (id)sender;
@end

Controller.m:

/* All Rights reserved */

#import <AppKit/AppKit.h>
#import "Controller.h"

@implementation Controller

- (void) showCurrentTime: (id)sender
{
   /* insert your code here */
}

這兩個檔案是 Gorm 產生的程式碼. 其中 -showCurrentTime 有個傳入一個 sender, 指向呼叫這個 method 的物件, 也就是 "Get Current Time" 按鈕. 因為 -showCurrentTime 有個傳入值, 所以在 Gorm中, 其名稱後要有個冒號才行. 在 Controller.h 中, 有一個變數 (outlet) label 及一個 meghod (action): showCurrentTime. label 這個 outlet 指的就是使用者介面上的字串. 對這個 outlet 做的改變都會反應在該字串上. 而當使用者按下 "Get Current Time" 按鈕時, 便會呼叫 -showCurrentTime 這個 method. 這便是 outlet 及 action 的作用, 目的在連結 Gorm 製做的使用者介面及程式碼.

加入程式碼如下:

Controller.m:

/* All Rights reserved */

#import <AppKit/AppKit.h>
#import "Controller.h"

@implementation Controller

- (void) showCurrentTime: (id)sender
{
   /* insert your code here */
  NSCalendarDate *date = [NSCalendarDate date];
  [date setCalendarFormat: @"%H : %M : %S"];
  [label setStringValue: [date description]];
}

[NSCalendarDate date] 會產生目前的時間, 設定好格式之後, 傳成字串放到 label 中. 當使用者按下 "Get Current Time" 按鈕之後, label 便會顯示目前的時間. 要注意的是 [NSCalendarDate date] 傳回的物件已經被自動釋放 (Autorelease) 了, 在此不需要再釋放一次.

最後加上 main.m 及 GNUmakefile 即可.

main.m:

#import <AppKit/AppKit.h>

int main(int argc, const char *argv[]) 
{
   return NSApplicationMain (argc, argv);
}

GNUmakefile:

include $(GNUSTEP_MAKEFILES)/common.make

APP_NAME = TimeMachine
TimeMachine_HEADERS = Controller.h
TimeMachine_OBJC_FILES = main.m Controller.m
TimeMachine_RESOURCE_FILES = TimeMachineInfo.plist TimeMachine.gorm
TimeMachine_MAIN_MODEL_FILE = TimeMachine.gorm

include $(GNUSTEP_MAKEFILES)/application.make

在這個範例中, 使用者介面的擁有者 (NSOwer) 是 NSApp, 但是其控制者是 Controller 物件. 在有些情況下, 其擁有者可以是其控制者, 也是 NSApp 的代理者. 程式開發者可以自由決定這些物件間的關係.