Section 3.14 メニュー

今回は新しいクラスの話ね。
なんか次々と新しいクラスが出てくるよねぇ。
んー、でも3章で紹介するネイティブクラスはこれが最後だよ。
あ、そうなんだ。
それで、今回はどんなクラスなの?
今回は MenuItem クラス を使ってメニューバーを作るの。
メニューバーって、ウィンドウのタイトルバーの下にある、「ファイル」とか「ヘルプ」とか表示されてるあれのことだよね?
そ、それのこと。
そのメニュー項目を管理するのが MenuItem クラス。
どんなメニューを作るの?
最初は簡単な「終了」から作ってみるね。
この項目を選択すると、ウィンドウを閉じるの。
うん、りょーかい。
じゃあ、スクリプトを書いてみるね。

<「終了」メニュー>

class MenuWindow extends Window
{
    var mi_quit;  // メニュー項目オブジェクト

    // コンストラクタ
    function MenuWindow()
    {
        super.Window();  // スーパークラスのコンストラクタを呼び出します

        // 「終了」メニューを作ります
        mi_quit = new MenuItem(this"終了(&Q)");
        // 「終了」メニューをウィンドウのルートメニューオブジェクトの子メニューとして登録します
        menu.add(mi_quit);

        visible = true;
    }

    // デストラクタ
    function finalize()
    {
        super.finalize();  // スーパークラスのデストラクタを呼び出します
    }

    // action メソッド
    function action(ev)
    {
        if(ev.target == mi_quit && ev.type == "onClick")
        {
            // 「終了」メニューがクリックされた場合は、ウィンドウを閉じます
            close();
        }
    }
}

var win = new MenuWindow();  // ウィンドウを作ります

まずは実行だね。
はーい!

<実行結果>

実行の結果表示されたウィンドウ

「終了」っていう項目があるメニューバーが表示されてるね。
じゃあ、「終了」をクリックしてみて。
あ、ウィンドウが閉じた。
これで動作確認はできたから、次はスクリプトを見てくね。
最初はコンストラクタからだよね。
ん、そだね。
まず、MenuItem クラスのコンストラクタには引数が2つあるんだ。

MenuItem クラスのコンストラクタの引数>
引数名引数の意味デフォルト値
第1引数windowこのメニュー項目を作成するウィンドウなし
第2引数captionメニュー項目に表示する文字列""(空文字列)

第1引数はこのメニュー項目が表示されるウィンドウってことなんだよね?
ん、だから this になるわけだね。
第2引数は、メニュー項目に表示する文字列になってるけど…
第2引数に指定してる文字列は "終了(&Q)" なのに、 実際に表示されてる文字列は『終了(Q)』になってるよ?
これは、Alt キーと Q キーを押すことでこの項目が選択できるようにするための書き方なんだ。
そういえばメニューの項目って Alt キーを使うとキーボードだけで選択できるよね。
& の後に文字を書くと、Alt キー+その文字のキーでメニュー項目が選択できるようになるんだ。
今回は &Q だから Alt キー+ Q キー で選択できるってワケ。
なるほどね〜。
で、メニュー項目を作った後は、MenuItem クラスの add メソッドを使って、 このメニュー項目をウィンドウのルートメニューの子メニューとして登録すると、ウィンドウのタイトルバーにこのメニュー項目が表示されるんだ。
?? えっと、よくわかんないんだけど…?
んー、じゃまずは Window クラスの menu プロパティから説明するね。
う、うん。
Window クラスはルートメニューオブジェクトっていうメニューオブジェクトを元々持ってて、 ウィンドウにメニューバーを表示する時は、ルートメニューオブジェクトにメニュー項目を登録する必要があるんだ。
じゃあ、そのルートメニューオブジェクトっていうのが menu プロパティで参照できるの?
ん、そう。
で、ルートメニューオブジェクトに登録するのに add っていうメソッドを使うの。
これでメニュー項目がルートメニューオブジェクトの子メニューとして登録されるんだ。
メニューにもレイヤみたいに親子関係があるの?
うん、あるよ。
これがメニューの親子関係だよ。

<メニューの親子(孫)関係>

メニューの親子関係

こういうふうになってるメニューって確かに見たことあるね。
これがメニューの親子関係なんだ。
ちなみに、「親メニュー」って書いてあるメニュー項目の親メニューがウィンドウのルートメニューね。
ルートメニューってレイヤで言うとプライマリレイヤみたいなものってことなのかな?
うん、そんな感じだね。
じゃあ、ここで1つ問題ね。
もしかして、子メニューを作りなさいっていう問題?
ん、そのとーり。
さっきの「終了(Q)」っていうメニュー項目を「ファイル(F)」っていう項目に書き換えて、 「ファイル(F)」の子メニューとして「終了(Q)」を作ってみて。
えっと、子メニューってどうやって作ったらいいの?
MenuItem クラスの add メソッドを使えば作れるよ。
こんなふうに。

<子メニューを作る例>

var parentMenu = new MenuItem(window_object, "親メニュー");  // 親メニューオブジェクトを作ります
var childMenu  = new MenuItem(window_object, "子メニュー");  // 子メニューオブジェクトを作ります
parentMenu.add(childMenu);  // childMenu を parentMenu の子メニューとして登録します

あ、ルートメニューオブジェクトに登録する時と同じなんだね。
そう。これでできるよね?
うん、やってみるね。

<「ファイル」メニューと「終了」メニュー>

class MenuWindow extends Window
{
    var mi_file;  // 「ファイル」メニュー項目オブジェクト
    var mi_quit;  // 「終了」メニュー項目オブジェクト

    // コンストラクタ
    function MenuWindow()
    {
        super.Window();  // スーパークラスのコンストラクタを呼び出します

        // 「ファイル」メニューを作ります
        mi_file = new MenuItem(this"ファイル(&F)");
        // 「終了」メニューをウィンドウのルートメニューオブジェクトの子メニューとして登録します
        menu.add(mi_file);

        // 「終了」メニューを作ります
        mi_quit = new MenuItem(this"終了(&Q)");
        // 「終了」メニューを「ファイル」の子メニューとして登録します
        mi_file.add(mi_quit);

        visible = true;
    }

    // デストラクタ
    function finalize()
    {
        super.finalize();
    }

    // action メソッド
    function action(ev)
    {
        if(ev.target == mi_quit && ev.type == "onClick")
        {
            // 「終了」メニューがクリックされた場合は、ウィンドウを閉じます
            close();
        }
    }
}

var win = new MenuWindow();  // ウィンドウを作ります

action メソッドはそのままでいいはずだから…
こんな感じかな。
じゃ実行してみよ。
うん。

<実行結果>

実行の結果表示されたウィンドウ

うん、「終了」をクリックするとちゃんとウィンドウが閉じるよ。
Alt + F + Q でも閉じれるし。
ん、これで OK だね。
あと、第2引数に "-"(半角マイナス)を指定するとセパレータが作れるから。
セパレータって?
セパレータってのはこれのこと。

<セパレータ>

セパレータ

あ、これもよく見かけるよね。
セパレータはメニュー項目をグループごとに区切ったりするのによく使われるからね。
じゃ、最後にショートカットキーについて説明しとくね。
ショートカットキー?
例えば、ファイルを開く時って Ctrl キーと O キーを一緒に押すと、メニュー項目をクリックしなくてもファイルの選択ダイアログが表示されるでしょ。
うん、あの機能って便利だよね。
それがショートカットキーなの?
ん、そう。
ショートカットキーは shortcut っていうプロパティで設定できるんだ。
例えば、Ctrl キーと Q キーでウィンドウを閉じるようにする場合はこう設定するの。

<ショートカットキーの例>

// 「終了」メニューを作ります
mi_quit = new MenuItem(this"終了(&Q)");
// Ctrl キー + Q キーで終了できるようにショートカットキーを設定します
mi_quit.shortcut = "Ctrl+Q";
// 「終了」メニューをウィンドウの「ファイル」の子メニューとして登録します
mi_file.add(mi_quit);

さっきのスクリプトの「終了」メニューを作る部分をこのスクリプトで置き換えて実行してみて。
はーい。

<実行結果>

ショートカットキーを設定したメニュー

メニューの項目のところに『Ctrl+Q』って表示されたね。
これでショートカットキーが設定されてることが判るよね。
じゃ、Ctrl + Q を押してみて。
うん、確かにウィンドウが閉じるね。
ショートカットキーは「シフト系キー+対象キー名」の組み合わせ、もしくは「対象キー名」で指定できるから、 例えばこういうふうに指定できるよ。

<ショートカットキー指定の例>
shortcut プロパティの値ショートカットキー
"F1"F1 キー
"Ctrl+A"Ctrl キー + A キー
"Shift+Esc"Shift キー + Esc キー
"Alt+Enter"Alt キー + Enter(Return) キー
"Shift+Alt+B"Shift キー + Alt キー + B キー
※但し、予め用途の決まっているキー(Tab, Shift+F1, Shift+F2, Shift+F3, Shift+F4 など)は設定できません。

色んな組み合わせが指定できるんだね。
うん。でも、設定する時は使いやすさを考えてね。
ファイルを開く時は Ctrl+O、上書き保存する時は Ctrl+S っていう感じに、 よく使われてるショートカットキーがある時は、それに合わせた方が使いやすいと思うよ。
うん、そうだね。
じゃあ、メニューについてはこんなところかな。
次回からは時計に機能を追加していくね。
設定した時間が来たらアラームを鳴らす機能とか?
ん、そういうの。
それじゃ、また次回ね!


前へ | TOP | 次へ