Section 3.12 例外処理(その1)

前回WaveSoundBuffer クラスの open メソッドを使ったよね。
サウンドファイルを開くメソッドだったよね。
ん、そだね。
じゃあ、前回のスクリプトの…

buffer.open("alarm.wav");

って書いてある行を…

buffer.open("startup.tjs");

って書き換えて実行したらどうなると思う?
えっ? startup.tjs って WAVE 形式のファイルじゃないでしょ?
うん、もちろん普通のテキストファイルだよ。
…だよねぇ。
それじゃ再生できないから、エラーになっちゃうんじゃない?
んじゃ実際にやってみよっか。

<実行結果>

実行の結果表示された例外メッセージ

やっぱり例外が起きちゃったね。
例外が起きると、そこで実行が止まっちゃうよね。
うん、そだね。
でも、指定されたファイルが正しくないだけなら、そこで実行を止めなくても、例えばエラーメッセージを表示して、 もう一回ファイルを指定し直してもらうっていう方法とかもあるよね。
確かにそうだけど、そんなことできるの?
うん、できるよ。
というワケで、今回は例外処理のやり方を説明するね。
例外処理?
例外処理をすると、例外が起こっても実行を続けられるんだ。
例えばこんな感じ。

<例外処理の例>

// FileSelector.tjs から FileSelector クラスの定義を読み込みます
Scripts.execStorage("FileSelector.tjs");

class SoundWindow2 extends Window
{
    var selector;  // FileSelector クラスのオブジェクト
    var buffer;    // WaveSoundBuffer クラスのオブジェクト

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

        // FileSelector クラスのオブジェクトを作ってウィンドウに管理してもらいます
        selector = new FileSelector();
        add(selector);

        // WaveSoundBuffer クラスのオブジェクトを作ってウィンドウに管理してもらいます
        buffer = new WaveSoundBuffer(this);
        add(buffer);
        buffer.looping = true;  // ループ再生します

        caption = "ファイルが開かれていません";  // ウィンドウのタイトルバーの文字列を設定します
        visible = true;
    }

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

    // サウンドファイルを開くメソッド
    function open()
    {
        try
        {
            // このブロック内で発生した例外が捕捉されます
            if(selector.openFile())
            {
                // ファイルが選択された場合はそのファイルを開きます
                buffer.open(selector.name);
                // 開かれたファイル名をウィンドウのタイトルバーに表示します
                caption = Storages.extractStorageName(selector.name) + " が開かれています";
            }
        }
        catch(e)
        {
            // try ブロック内で例外が起きるとこのブロック内のスクリプトが実行されます
            System.inform(e.message);  // 例外の内容を表示します
            caption = "ファイルが開かれていません";
        }
    }

    // サウンドを再生するメソッド
    function play()
    {
        if(buffer.status == "stop")
            buffer.play();  // 現在停止中であれば再生を開始します
    }

    // サウンドの再生を停止するメソッド
    function stop()
    {
        if(buffer.status == "play")
            buffer.stop();  // 現在再生中であれば再生を停止します
    }

    // action メソッド
    function action(ev)
    {
        // ウィンドウに対する onKeyDown イベントを処理します
        if(ev.target == this && ev.type == "onKeyDown")
        {
            if(ev.key == VK_O)
                open();  // O キー → ファイルを開く
            else if(ev.key == VK_P)
                play();  // P キー → 再生
            else if(ev.key == VK_S)
                stop();  // S キー → 停止
        }
    }
}

// ogg 形式のファイルを再生する場合は、krkr.eXe のあるフォルダに wuvorbis.dll をコピーしてから
// 下の行のコメントを外してください
// Plugins.link("wuvorbis.dll");

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

実行する前に FileSelector.tjs をプロジェクトフォルダに置いてね。
必要なファイルはここに置いとくから。
FileSelector.tjs って何のファイルなの?
§2.8で作った FileSelector クラス の定義を書いたファイルだよ。
今回はサウンドファイルを選択するのにこのクラスを使うんだ。
クラスの定義って startup.tjs に書かなくてもいいの?
うん。他のファイルに書いてあるスクリプトを読み込めるからね。
あ、そうなんだ。
詳しいことは後で説明するから、とりあえず実行してみて。
うん、わかった。

<実行結果>

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

ウィンドウが表示されたね。
タイトルバーに「ファイルが開かれていません」って表示されてるけど?
それはサウンドファイルが開かれてませんっていう意味。
じゃあ、O キーを押してみて。
おっけー。

<ファイル選択ダイアログ>

表示されたファイル選択ダイアログ

あっ、ファイル選択ダイアログが表示された。
適当なサウンドファイルを選んで「開く」ボタンを押してみて。
じゃあ、test フォルダにある alarm.wav を開いてみるね。

<ファイルを選択した後のウィンドウ>

ファイルを選択した後のウィンドウ

タイトルバーに「alarm.wav が開かれています」って表示されたね。
でも、アラームは鳴ってないよ?
まだファイルを開いただけだからね。
今度は P キーを押してみて。
あ、アラームが鳴った!
止める時は S キーね。
うん、S キーを押すと止まったね。
じゃあ、もう一回 O キーを押して、今度は startup.tjs を開いてみて。
例外を起こすんだね。
えっと、O キーを押して、startup.tjs を選択して「開く」、と。

<例外メッセージ>

表示された例外メッセージ

あっ、今度はさっきとちょっと違うメッセージが表示されたね。
しかも実行が止まってないでしょ。
ほんとだ。
OK ボタンを押した後も普通に実行が続いてるね。
それじゃ、スクリプトを見ていくね。
例外処理の部分以外は解ると思うから、今回は例外処理をしてる open メソッド だけ見ていくね。
うん、りょーかい!
…っと、その前に execStorage メソッド を説明しとかなきゃね。
あ、それって FileSelector クラスの定義が書いてあるファイルを読み込むためのメソッド?
そうそう。
Scripts クラスの execStorage メソッドは、 第1引数に指定されてるファイルを読み込んで TJS スクリプトとして実行するメソッドなんだ。
なんかこのメソッドって、KAG の call タグと似てない?
確かに似てるね。
でも TJS にはラベルがないから、call タグみたいにラベルの指定はできないし、 return タグみたいに、途中で読み込みをやめて戻ってくる命令もないんだ。
じゃあ、ファイルの最初から最後まで全部読み込んじゃうってこと?
ん、そういうこと。
じゃあ、改めて open メソッド を見ていくね。
例外処理は、例外を捕捉する try ブロックと、 例外が起こった時に実行される catch ブロックで出来てるんだ。
try ブロックと catch ブロック?
try ブロックの中に例外が起きるかもしれないスクリプトを書いておくと、 例外が起きた時に catch ブロックの中身が実行されるんだ。
えっと、再生できないファイルを選択して buffer.open を呼び出すと例外が起きるから、 ファイルを選択して開く部分のスクリプトを try ブロックの中に書いてるってこと?
うん、そういうこと。
もしファイルを開く時に例外が起きたら、その後に書いてある caption プロパティを設定するスクリプトは実行されずに、 すぐに catch ブロックの中身が実行されるんだ。
ってことは、例外が起こったらすぐに catch ブロックに書いてある inform メソッドが実行されるの?
そだよ。
で、inform メソッドでどんな例外が起こったかを表示してるんだ。
inform メソッドの引数が e.message になってるけど、これってなんなの?
e』っていうのは、例外が起こった時に catch ブロックで受け取れる、 例外に関する情報を持ってる Exception クラス のオブジェクトなんだ。
e.message は例外の内容を表すメッセージ文字列だよ。
へぇ…そんなクラスもあるんだね。
ちなみに Exception クラスのオブジェクトの事を例外オブジェクトって呼ぶんだ。
例外オブジェクト、ね。
で、もし例外が起こらなかった場合は、catch ブロックの中身は実行されないんだ。
じゃあ、例外が起こらなかったら、ファイル名をタイトルバーに表示して終わりってこと?
ん、そう。
あ、そういえば extractStorageName って初めて見るメソッドだよね?
extractStorageName メソッドは Storages クラスのメソッドで、 パス名を取り除いたファイル名を取得するメソッドだよ。
えっと、具体的にはどんな感じになるの?
例えば、Storages.extractStorageName("tjs/test/startup.tjs") の戻り値は "startup.tjs" になるよ。
つまり、そのファイルが置いてあるフォルダ名を取り除いて、ファイルの名前だけを取得できるってこと。
なるほど、そういうことね。
じゃあ、今回はここまでね。
次回はこの続きをやるよ。
次回も例外処理?
うん、もうちょっと説明することがあるから。
それじゃ、また次回ね。


前へ | TOP | 次へ