Ubuntu Weekly Recipe

第424回 GUIプログラムをPython/Ruby/ECMAScriptで書く

この記事を読むのに必要な時間:およそ 6.5 分

共通処理について

Python 3/Ruby/ECMAScriptで記述されたプログラムを示しましたが,これらのコードを比較すると,次の2つの共通点を見出せます。

  1. windowの機能を実装したオブジェクトを作成し,Gtk.main()を呼ぶ。
  2. そのオブジェクトは初期化の過程で,レイアウトを決定されてウィジェットやイベントハンドラを付与される。

この2つの共通点について説明します。

ウィジェットの配置

まずは2番目についてです。今回のサンプルプログラムで使うBoxは,window内のレイアウトを決めるためのものです。ButtonやEntryはユーザーが操作するGUIパーツで,ウィジェットと呼ばれます。サンプルでは,次の流れで上下2段のレイアウトを作成し,合計4つのウィジェットを配置しています。

  1. vboxとして垂直ボックスを生成し,ウィンドウ内に配置。
  2. topboxとして水平ボックスを生成し,vboxに配置。
  3. buttonとしてボタンを生成し,topboxに配置。
  4. buttonとしてもうひとつボタンを生成し,topboxに配置。
  5. bottomboxとして水平ボックスを生成し,vboxに配置。
  6. entryとしてテキストエントリーを生成し,bottomboxに配置。
  7. labelとしてテキストラベルを生成し,bottomboxに配置。

2つのボタンには,クリック時の処理を記述した処理を登録しました。このような処理のことをイベントハンドラと呼びます。Gtk+3の作法では,connect()やsignal_connect()と言ったメソッドを使い,イベントハンドラとイベントの関連付けを行います注1⁠。

注1
正確にはGLib/GObjectの作法です。Gtk+3はGLib/GObjectのアプリケーションとして書かれています。
Gtk.main()でのループ処理

共通点の1番目で言及しているGtk.main()は,イベントループを回す関数です。プログラムが実行されここに到達すると,ループして終了しなくなります。ループ内では,ユーザーからの入力やデバイスへの出力,他のプロセスへの通信といったイベントを捕捉し,対応するハンドラを実行します。イベントループはこの処理を,システムに過度の負荷をかけることを避けつつ延々と行っています。

今回のサンプルで実装したイベントハンドラは,このイベントループ内で呼ばれます。サンプル内のイベントループはひとつなので,どう操作しようがイベントハンドラを同時に実行することはできない点に留意してください。すなわち,あるイベントハンドラがイベントループに処理をなかなか戻さないようにコード修正した場合,その間他のイベントを捕捉できませんので,アプリケーションの実行が止まったように見えるという問題が発生します。

ループに突入するとプログラムは終了しなくなりますが,それだと非常に不便です。今回のサンプルではプログラムを終了するためのチュートリアルとして,closeボタンを実装しています。またPython 3とRubyのサンプルでは,Unixシグナルに対するハンドラを設定しました。サンプルを実行した端末上でキーボードのCtrlキーとCキーを同時押しすると,プログラムがSIGINTを捕捉してループを抜けます。gjsの場合は,プログラムしなくてもUnixシグナルを捕捉して終了するようです。

著者プロフィール

坂本貴史(さかもとたかし)

Ubuntuのマルチメディア編集環境であるUbuntu Studioのユーザ。主にUbuntu日本コミュニティとUbuntu Studioコミュニティで活動。いつかユーザ同士で合作するのが夢。