Kikuchy's Second Memory

技術のこととか、技術以外のこととか、思ったことを書き留めています。

Clojure で GUI アプリを書いてみる (例外キャッチ編)

今までの ClojureGUI アプリシリーズ





f:id:kikuchy:20130531103512p:plain



一旦完成を迎えた天気予報アプリですが、これが抱えている問題点に

「ネットに繋がってないと、キャッチされない例外が出て起動しない」

というのがあります。
私は MacBook (最後の黒 MacBook)を使っていてしょっちゅう移動しますし、必要無い時はテザリングを使わないので、オフライン環境にいる事がままあります。
天気予報アプリをログイン項目に追加してあるせいで、オフラインのまま Mac を立ち上げると、キャッチされない例外のダイアログが出て鬱陶しいのです。

そこで、改良することにしました。
方針は以下のように。

  • 起動時に出る例外をキャッチ
  • アイコンを天気予報アイコンではなく、ネットに繋がっていない事がわかりやすいようなものにする

さっそくコードをいじります。
変更したのは、前々回の -main のコードのみ。

(defn -main
  [& args]
  (try
  ;; ネットに繋がらないと、 get-tenki が例外を出す
    (let [today-forecast (tenki-today (get-tenki))
    icon (system-tray-icon (read-image-local (nth icon-images-list (telop-to-index (:telop today-forecast)))) (tenki-temperature today-forecast) (system-tray-popupmenu))]
    (add-icon-system-tray icon))
    (catch Exception _ 
      (add-icon-system-tray (system-tray-icon (read-image-local "no_connection.png") "インターネットに接続できませんでした" (system-tray-popupmenu))))))

例外を発生させる get-tenki が let の中に入ってしまっている上、 today-forecast の次に束縛している icon の中で today-forecast を使う物ですから、 let ごと try で囲んでしまいました。
あまり奇麗なコードではないですね。
正常系の中で何かしらの例外が出た場合に、 "no_connection.png" をアイコンにして、ツールチップを設定し、システムトレイにアイコンを追加しています。


そして出来上がりは冒頭のスクリーンショットのようになりました。
これでもう、いちいち例外のダイアログを閉じなくてもOK!


Clojure の try - catch - finally の使い方はこうらしいです。

(try
  (何か例外が出そうな処理)
  (catch
    (例外のクラス名) (例外を束縛する変数名) (例外が起きたときの処理。 例外が起きたら、ここの戻り値が try の戻り値になる)
  (finally
    (例外が起きても起きなくても行う処理)))

面白いのは、 try が値を返す事。例えば

(try
  1
  (catch
    Exception _ 2)
  (finally
    3))

上のコードの評価値は 1 。そして、

(try
  1
  (throw (Exception. "Errorrrrrr"))
  (catch
    Exception _ 2)
  (finally
    3))

このコードの評価値は 2 になります。 finally の値は try の値にはならないようですね。

ちなみに、 catch はいくつでも書けて、 finally は省略可。この辺は Java と変わりません。