1
2
3
4
5
6
7
3-2
RAD Studio
で
Hello world
を作る
3-2
RAD Studio
でHello world
を作るさて、ではいよいよRAD Studioを触っていきます。RAD Studioを起動してメニューの 「ファイル」→「新規作成」から「FireMonkeyモバイルアプリケーション」を選択します(図 3.11)。 図3.11●プロジェクトの新規作成メニュー 次に、種類を選択するダイアログが開くので、空のアプリケーションを選択します(図 3.12)。 図3.12●アプリケーションの種類選択ダイアログ
3
初めての iOS アプリケーション するとiPhoneの画像が表示されたFormが表示されるので、第2章でやったように、ツール パレットからTLabelとTButtonを置いてみます(図3.13)。 図3.13●コントロールの配置 さて、ここからボタンとイベントを関連づけます。Button1を選択した状態で、オブジェク トインスペクタのイベントタブでOnClickをダブルクリックするか、Button1そのものをダブ ルクリックします(図3.14)。1
2
3
4
5
6
7
図3.14●イベントハンドラの指定 するとイベントハンドラが定義されるのでLabel1.Text := 'Hello world !';
と書きます。これで、もう終わりです。第2章と同じようにプロジェクトを保存して実行する と、Hello world !アプリが起動します(図3.15)。
3
初めての iOS アプリケーション 図3.15●実行結果 デフォルトイベント コントロールのデフォルトイベントを定義できます。たとえば TButton のデフォルトイベ ントは OnClick になっているので、ボタンそのものをダブルクリックすると OnClick イベ ントハンドラが生成されます。前章と合わせて、RAD StudioとXcodeでの開発を簡単に説明してきました。「Hello world」 のような簡単なアプリではあまり差はないように思われるかもしれません。しかし、Xcodeの ようにControlでドラッグしてコネクションを設定する、という手順よりも、RAD Studioのよ うにオブジェクトインスペクタで必要なイベントをダブルクリックしてイベントハンドラを作 る方が直感的ではないでしょうか。また、前章で説明したように、RAD Studioは2Way-Tools
なのでIDE上での変更は即座にコードに反映され、不整合が起きないようになっています。 他にも、Xcodeにはコネクションを直感的かつ俯瞰的に見るツールがありませんが、RAD
Studioにはオブジェクトインスペクタがあり、どのコントロールのイベントがどのような名前
1
2
3
4
5
6
7
で定義されているのかを簡単に知ることができます。しかも、この開発スタイルはWindowsで もiOSでも、近々サポートされるAndroidであっても変わることがありません。あるバージョ ンからUIが大きく変わったり、InterfaceBuilderからStoryboardを使うように変わるといった こともほとんどありません。そのため、WindowsプログラマでもDelphiの経験があればすんなりとiOSの開発に入れま すし、これからプログラミングを始める方々なら、一度Delphiに触ってしまえばさまざまなプ ラットフォームに対応できるのです。
FireMonkey が Windows 上でも実行可能であることの意味
FireMonkey で作成した iOS アプリケーションは PAServer を経由して実行するため、ア プリケーションの配置にそこそこ時間が掛かります。毎回、この時間を待つのは苦痛かもし れません。 しかし、FireMonkey はマルチプラットフォームに対応したフレームワークです。ターゲッ ト OS を Windows にすれば、そのまま Windows で動作するアプリケーションになります。 そのアプリケーションは当然 PAServer を経由しないため、コンパイル後すぐに実行されま す。つまり、Windows 上で実行しながら大枠の動きを確認しつつ、要所要所で iOS シミュ レータや iOS デバイスで実行するということが簡単にできるのです。これは開発効率の向上 に大いに寄与することでしょう。
3-3
カップラーメンタイマーを作ろう
3-3
カップラーメンタイマーを作ろうさて、それではここからはXcodeのことを忘れて、RAD Studioで色々作っていきましょう。 まずは、簡単なカップラーメンタイマーを作ります。ただ3分経ったらアラームが鳴る、とい うのでは生麺タイプのカップラーメンに対応できないので、何分経ったら鳴るか設定できるよ うにしましょう。新しくFireMonkeyモバイルアプリケーションを作成します。
プロジェクト名は「CupRamenTimer.dproj」、ユニットは「uMain.pas」として保存します。
3
初めての iOS アプリケーションユーザーインターフェースの作成
では、Form1をクリックして、まず名前を変えます。コンポーネントの名前は、オブジェク トインスペクタのNameプロパティを編集すると変更できます。ここでは「frmMain」としま す(図3.16)。 図3.16●Nameプロパティ 次に、ツールパレットでTToolBarを検索して、フォームにドロップします(図3.17)。 図3.17●Alignプロパティ TToolBarをドロップすると、自動的にTToolBarが画面最上部に配置されたと思います。こ1
2
3
4
5
6
7
れは、Alignプロパティの作用です。Alignプロパティに「alTop」という値を設定すると、画面上部に配置され動かすことができなくなります。 Alignプロパティの代表的な値について、表3.1にまとめます。 表3.1●Alignプロパティの代表的な値 値 説明 alTop 親領域の上部にフィット。幅は親領域の幅と同じ大きさ。 alBottom 親領域の下部にフィット。幅は親領域の幅と同じ大きさ。 alLeft 親領域の左部にフィット。高さは親領域の高さと同じ大きさ。 alRight 親領域の右部にフィット。高さは親領域の高さと同じ大きさ。 alClient 親領域の空いている領域にフィットする大きさになる。 alCenter 親領域の中央に表示される。 これらの値は画面が回転しても有効で、回転に追随し位置を自動的に変更します。
ToolBarの名前は「barTitle」とでもしておきましょう。次にTLabelを置き、構造ペインで
ToolBarの子にします。名前は「lblTitle」とし、Textプロパティに「カップラーメンタイマー」 と入れます(図3.18)。
3
初めての iOS アプリケーション しかし、ラベルの内容の表示が少し変です。これは、ラベルの幅が足りないため、ラベルの 内部で文字列が改行されてしまったためです。グリップを掴んで幅を広げても構わないのです が、ここではAutoSizeプロパティを使いましょう。AutoSizeプロパティにチェックを入れて Trueにします。この変更は即座に反映され、ラベルの中身の文字列に合わせて自動的にラベル の幅と高さが変わります(図3.19)。ラベルを使う際、AutoSizeは非常に便利なので覚えてお くと良いプロパティの1つです。 図3.19●AutoSizeプロパティ さて、ラベルの文字は表示されるようになりましたが、まだiOSらしくはありません。iOS でToolBarに表示される文字列と同じように表示させるためには、StyleLookupプロパティを 使います。StyleLookupプロパティをクリックするとコンボボックスが開き、このコンポーネ ントに適用できるスタイルの一覧が表示されます(図3.20)。1
2
3
4
5
6
7
図3.20●StyleLookupプロパティToolBarに表示するラベルなので、StyleLookupは「toollabel」を選びます。すると自動的に フォントカラーなどが変わってToolBarらしい表示になりました(図3.21)。
3
初めての iOS アプリケーションそれから、ラベルの位置も中途半端なので調整しておきましょう。Alignプロパティを 「alClient」にします。AutoSizeプロパティはTrueのままでも問題がありませんが、必要なくな
るのでFalseにします(図3.22)。 図3.22●Alignの設定 ラベル内に表示するテキストの位置はTextAlignプロパティで設定します。TextAlignプロパ ティに設定する値を表3.2に示します。 表3.2●TextAlignの値 値 説明 taCenter 中央寄せ taLeading 左寄せ taTrailing 右寄せ ここではテキストを中央寄せにするために「taCenter」にします(図3.23)。
1
2
3
4
5
6
7
図3.23●TextAlignプロパティ これでタイトル部分はそれっぽくなりました。 次に、アラームが鳴るまでの時間を指定するコントロールと、その時間を分単位で指定する ことを示すラベルを2つ置きます。ここでは、時間を指定するコントロールにはTSpinBoxを 使いましょう。名前は、それぞれ「spinTimer」、「lblTimerPrefix」、「lblTimerSuffix」としました。 また、ラベルはAutoSizeプロパティをTrueにしてあります(図3.24)。lblTimerPrefixのTextプロパティには「じゃぁ、いつ鳴らすの?」を、lblTimerSuffixのTextプロパティには「分後 でしょ」の文字列をそれぞれ設定します。
3
初めての iOS アプリケーション 図3.24●SpinBoxとプロパティ この3つのコンポーネントは、まとめて中央寄せにしてみましょう。[Ctrl]キーを押しなが らドラッグすることで複数のコンポーネントを一度に選択できるので、そうして選択したコン ポーネント群を右クリックして「位置揃え」を選択します(図3.25)。 図3.25●複数のコンポーネントを選択し、位置揃えを行う1
2
3
4
5
6
7
すると、「位置揃え」ダイアログが現れるので、「水平位置揃え」を「ウィンドウの中央に置く」 にします(図3.26)。 図3.26●位置揃えダイアログ これで中央に揃いました(図3.27)。 図3.27●選択したコントロールが中央に揃う さらに、ラベルを2つとボタンを1つ追加し、次のように設定します。 (1)ラベル 名前 lblRestTimePrefix Textプロパティ 残り3
初めての iOS アプリケーション (2)ラベル 名前 lblRestTime Textプロパティ 00:00 Font.Sizeプロパティ 64 Font.Styleプロパティ fsBold (3)ボタン 名前 btnStart Textプロパティ 開始 (1)のラベルは、(2)のラベルの内容の説明に使います。(2)のラベルには、タイマーが開 始してからの残り時間を秒単位で表示します。文字が目立つように、大きなサイズで太字で表 示するようにしています(図3.28)。また、先ほどの位置揃えダイアログを使ってウィンドウ の中央に配置しましょう。(3)のボタンはタイマーをスタートさせるために使います。 図3.28●Fontプロパティ 今度は、非ビジュアルコンポーネントを2つ貼ります。TTimerとTMediaPlayerです。TTimerはIntervalプロパティで設定した時間(ミリ秒)が経過したときにOnTimerイベントを 発生させます。この機能を使って指定した分数の後にイベントが来るようにしましょう。
1
2
3
4
5
6
7
Timerの名前は「timerRestTime」としました。今回のアプリケーションの有効数字は1秒で すが、少し精度を上げるためにIntervalプロパティには「500」を設定します。ここで重要なの がEnabledプロパティです。TimerのイベントはEnabledプロパティがTrueの場合に発生します。 ここでは、開始ボタンを押してからTimerイベントが発生して欲しいので、Enabledプロパ ティはFalseにしておきます。 TMediaPlayerは指定した音声ファイルを再生するコンポーネントです。FileNameプロパ ティにMP3ファイルを指定して、Playメソッドを呼ぶだけです。2つ貼った状態が図3.29 です。 図3.29●TTimerとTMediaPlayer 次に、実際に鳴らすMP3を配布パッケージ(IPA)に含めます。そこで使うのが「配置マネ ージャ」です。配置マネージャは、メニューの「プロジェクト」→「配置」で起動します(図 3.30)。3
初めての iOS アプリケーション図3.30●配置マネージャを開くメニュー
配置マネージャの「ファイルの追加」ボタンから、鳴らすMP3ファイルを選択します(図
3.31、図3.32)。
1
2
3
4
5
6
7
図3.32●MP3を選ぶダイアログ 追加されると図3.33のようになります。 図3.33●MP3が追加される ここでリモートパス欄をクリックして、リモートパスを「.¥StartUp¥Documents」に修正しま す(図3.34)。3
初めての iOS アプリケーション 図3.34●パスの修正 こうすると、Documents/alarm.mp3として参照できるようになります。このように簡単にリ ソースを含めることができます。 さて、ここまででGUIができました。構成ペインは次のようになっていると思います。 frmMain barTitle (TToolBar) lblTitle (TLabel) btnStart (TButton) lblRestTime (TLabel) lblRestTimePrefix (TLabel) lblTimerPrefix (TLabel) lblTimerSuffix (TLabel) spinTimer (TSpinBox) playerAlarm (TMediaPlayer) timeRestTime (TTimer) ※構成ツリーのコンポーネントの名前の後ろの括弧内はコンポーネントのクラス名コーディング
では、次にコーディングに入ります。作成するイベントハンドラは、btnStartのOnClick、1
2
3
4
5
6
7
トハンドラはダブルクリックで作成できます。 ソースコードを次に示します。 リスト3.3●カップラーメンタイマーのソースコード unit uMain; interface usesSystem.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.StdCtrls, FMX.Edit, FMX.Media; type TfrmMain = class(TForm) barTitle: TToolBar; lblTitle: TLabel; spinTimer: TSpinBox; lblTimerPrefix: TLabel; lblTimerSuffix: TLabel; lblRestTime: TLabel; btnStart: TButton; lblRestTimePrefix: TLabel; timerRestTime: TTimer; playerAlarm: TMediaPlayer;
procedure btnStartClick(Sender: TObject); procedure timerRestTimeTimer(Sender: TObject); procedure FormCreate(Sender: TObject);
private { private 宣言 } // 変数宣言 ---① FTime: TDateTime; FTargetTime: Integer; FStarting: Boolean; // メソッド ---②
procedure SetAllEnabled(const iEnabled: Boolean); procedure SetTime(const iRestTime: Integer); public
{ public 宣言 } end;
3
初めての iOS アプリケーション var frmMain: TfrmMain; implementation uses System.DateUtils; // ユニットの使用を宣言 ---③ {$R *.fmx} // btnStart の OnClick イベントハンドラ ---④procedure TfrmMain.btnStartClick(Sender: TObject); begin
if (FStarting) then begin SetAllEnabled(False); end else begin if (spinTimer.Value = 0) then ShowMessage('何分後にアラームを鳴らすか選択してください') else begin FTime := Now; FTargetTime := Trunc(spinTimer.Value) * 60; SetAllEnabled(True); SetTime(FTargetTime); end; end; end; // frmMain の OnCreate イベントハンドラ ---⑤
procedure TfrmMain.FormCreate(Sender: TObject); begin playerAlarm.FileName := GetHomePath + PathDelim + 'Documents' + PathDelim + 'alarm.mp3'; end; // Enabled の切り替え ---⑥
procedure TfrmMain.SetAllEnabled(const iEnabled: Boolean); begin
FStarting := iEnabled;
timerRestTime.Enabled := iEnabled; spinTimer.Enabled := not iEnabled;
1
2
3
4
5
6
7
if (iEnabled) then begin btnStart.Text := '停止'; SetTime(FTargetTime); end else begin btnStart.Text := '開始'; SetTime(0); end; end; // lblRestTime に残り時間を表示 ---⑦
procedure TfrmMain.SetTime(const iRestTime: Integer); begin
lblRestTime.Text := Format('%.2d:%.2d', [iRestTime div 60, iRestTime mod 60]); end;
// timerRestTime の OnTimer イベントハンドラ ---⑧
procedure TfrmMain.timerRestTimeTimer(Sender: TObject); var
Diff: Integer; begin
Diff := SecondsBetween(Now, FTime); if (Diff > FTargetTime) then begin SetAllEnabled(False); playerAlarm.Play; ShowMessage('今でしょ!'); end else SetTime(FTargetTime - Diff); end; end.