Section 3.17 時計の実装(その3)

今回は前回の続き、action メソッド を作るとこからね。
今回の action メソッドって、やらなくちゃいけないことが多いよね。
タイマーイベントと、メニュー選択が4種類、あとクリックされたりキーが押されたりするとアラームを止める処理だね。
しかも複雑だよねぇ…
とりあえず、処理するイベントをまとめてみよっか。
そだね。

action メソッドで処理するイベント>
イベントtargettype処理内容
タイマーイベントtimer"onTimer"現在日時の表示を更新&アラームを鳴らすかチェック
「終了」メニュー選択menuQuit"onClick"ウィンドウを閉じる
「アラームファイルを設定」メニュー選択menuFile"onClick"ファイルの選択ウィンドウを表示&選択されたファイルを開く
「アラームを設定」メニュー選択menuSet"onClick"アラームの設定ダイアログを表示&アラームをセット
「アラームを解除」メニュー選択menuCancel"onClick"アラームの設定を解除
プライマリレイヤをクリックprimaryLayer"onClick"アラームを止める
キー押下this"onKeyDown"アラームを止める

これが今回の action メソッドで処理するイベント。
1、2、3……7つもあるね。
今回は switch を使って書いてみよっか。
switch …って、条件分岐するときに使うんだったよね?
そう。§1.13で使ったよね。
今回は target の種類が多いから switch を使った方がいいかなと思って。
ってことは、まず ev.target をチェックすればいいの?
ん、そういうこと。
つまりこんな感じだね。

function action(ev)
{
    switch(ev.target)
    {
    case timer:
        // ここにタイマーイベントの処理を書きます
        break;

    case menuQuit:
        // ここに「終了」メニューの処理を書きます
        break;

    case menuFile:
        // ここに「アラームファイルを設定」メニューの処理を書きます
        break;

    case menuSet:
        // ここに「アラームをセット」メニューの処理を書きます
        break;

    case menuCancel:
        // ここに「アラームを解除」メニューの処理を書きます
        break;

    case primaryLayer:
        // ここにプライマリレイヤがクリックされた時の処理を書きます
        break;

    case this:
        // ここにキーが押された時の処理を書きます
    }
}

ん〜っと、あとはそれぞれの処理をする部分で type をチェックして、 type が合ってたら、その処理に応じたメソッドを呼び出せばいいんだよね?
うん、そうそう。
じゃあ、後はやってみて。
おっけー。

action メソッド>

function action(ev)
{
    switch(ev.target)
    {
    case timer:
        // タイマーイベントの処理
        if(ev.type == "onTimer")
        {
            drawTime();    // 現在の日時の表示を更新します
            if(checkAlarm())
                playAlarm();  // アラームを鳴らす時刻になった場合はアラームを鳴らします
        }
        break;

    case menuQuit:
        // 「終了」メニューの処理
        if(ev.type == "onClick")
            close();  // ウィンドウを閉じます
        break;

    case menuFile:
        // 「アラームファイルを設定」メニューの処理
        if(ev.type == "onClick")
            setAlarmFile();  // アラーム用ファイル選択ダイアログを表示して、選択されたらそのファイルを開きます
        break;

    case menuSet:
        // 「アラームをセット」メニューの処理
        if(ev.type == "onClick")
            setAlarm();  // アラームをセットします
        break;

    case menuCancel:
        // 「アラームを解除」メニューの処理
        if(ev.type == "onClick")
            cancelAlarm();  // アラームの設定を解除します
        break;

    case primaryLayer:
        // プライマリレイヤがクリックされた時の処理
        if(ev.type == "onClick")
            stopAlarm();  // アラームを止めます
        break;

    case this:
        // キーが押された時の処理
        if(ev.type == "onKeyDown")
            stopAlarm();  // アラームを止めます
    }
}

できたよ〜。
うん、全部のイベントがちゃんと処理できてるね。
やった、これで完成だねっ!
あ、ちょっと待って。
えっ? これで完成じゃないの?
クリックでアラームを止められるようにするために、コンストラクタで日時表示用のレイヤの設定を追加しなくちゃいけないんだ。

<コンストラクタ内の日時表示用レイヤを作成している部分>

// 日時を書くためのレイヤを作ります
messageLayer = new Layer(this, primaryLayer);
add(messageLayer);
with(messageLayer)
{
    .setPos(22, 22, 114, 68);        // サイズを 114×68、位置を (22, 22) にします
    .font.face = "MS Pゴシック";  // フォントを「MS Pゴシック」にします
    .font.height = 24;               // フォントの高さを 24 ピクセルに設定します
    .hitThreshold = 256;             // マウス関係のメッセージを受け取らないようにします ← 追加
    .visible = true;
}

追加するのって、hitThreshold っていうプロパティ?
ん、そう。
これってどういうプロパティなの?
messageLayer って、プライマリレイヤより手前にあるでしょ。
うん。messageLayer はプライマリレイヤの子レイヤだもんね。
onClick メソッドは、基本的に一番手前にあるレイヤのが呼び出されるんだ。
それって、messageLayer の上でクリックしたら、プライマリレイヤじゃなくて、 messageLayeronClick メソッドが呼び出されるってこと?
デフォルトの設定だと、文字以外の部分をクリックした場合はプライマリレイヤの onClick メソッドが呼び出されるんだけど、 文字の上でクリックした場合は messageLayeronClick メソッドが呼び出されるんだ。
それじゃ、messageLayeronClick メソッドの処理も action メソッドの中に入れとかなきゃいけないんじゃないの?
それをやらなくてもいいようにするために、hitThreshold プロパティを設定するの。
それってどういうこと?
今回は hitThreshold プロパティの詳しい説明はパスさせてもらうけど、hitThreshold プロパティの値を 256 に設定すると、そのレイヤをクリックしても onClick メソッドが呼び出されなくなるんだ。
つまり、messageLayer をクリックしても、onClick メソッドが呼び出されないようにしてるってこと?
そ。
こうすると、messageLayer の領域をクリックした時に、messageLayer じゃなくて、 その奥にあるプライマリレイヤの onClick メソッドが呼び出されるようになるんだ。
へぇ、そうなんだ。
こうすれば、ウィンドウのクライアント領域のどこをクリックしても、 プライマリレイヤの onClick メソッドが呼び出されるってワケ。
なるほどね〜。
じゃあ、これで今度こそ完成?
ん、これで完成。
さすがに今回は長かったねぇ〜。
だね。スクリプトも長くなっちゃってるから、TJS ファイルにしてまとめとくね。
startup.tjs と FileSelector.tjs と Clock.tjs を全部プロジェクトフォルダに置いてから実行してね。
りょ〜かい!
んじゃ、実行してみよっか。
うん!

<実行結果>

表示されたウィンドウ

おー、ちゃんとメニューも表示されてるね〜。
うん。じゃ、アラームの設定もやってみよ。
まずアラーム用のファイルを設定するんだよね。
「アラーム」メニューの「アラームファイルを設定」を選択、だね。

<アラームファイルの設定>

「アラーム」メニューの「アラームファイルを設定」を選択

これでファイル選択のダイアログボックスが表示されるんだよね。

<「ファイルを開く」ダイアログボックス>

「ファイルを開く」ダイアログボックス

えっと、test フォルダにある alarm.wav を選択して、「開く」、と。
それじゃ次はアラームをセットしてみて。
「アラーム」メニューの「アラームをセット」を選択するんだよね。

<アラームの設定>

「アラーム」メニューの「アラームをセット」を選択

メニューを選択すると、何分後にアラームを鳴らすかを入力するウィンドウが表示されるんだよね。

<アラームの時間設定ダイアログ>

アラームの時間設定ダイアログ

何分後に設定しよっか?
ま、テストだし、とりあえず1分後でいいんじゃない?
うん、わかった。
じゃあ、『1』って入力して、OK、と。

<アラーム設定後のウィンドウ>

アラーム設定後のウィンドウ

マウスカーソルをプライマリレイヤの上に乗せると、アラームが鳴る時刻が表示されるね。
ん、タイトルバーもちゃんと「Alarm ON」になってるね。
んじゃ、アラームが鳴るまで1分待と。
うん。
………
………
1分後。
あっ、アラームが鳴った!
ウィンドウのクライアント領域をクリックするか、何かキーを押してアラームを止めてみて。
うん、じゃあウィンドウをクリックしてみるね。
……あ、アラームが止まった。
ん、ちゃんと動いてるね。
うんっ!
後でアラーム解除とか、キーを押してアラームを止めるチェックもしといてね。
は〜い!
それじゃ、今回はここまで。
また次回ね!


前へ | TOP | 次へ