Python + gtk + gladeでGUIアプリケーションの作成 その1
KVMをリモートで管理するため、virt-managerというアプリケーションを使用しました。UbuntuからリモートサーバーのKVMに接続し、仮想OSをインストールする
virt-manager、ソースを見てみるとPythonで書かれています。
こんなGUIアプリケーションがPythonで作れるとは。

自分でもPythonでGUIアプリケーションを作ってみたくなったので、調べてみました。
PyGTKのインストール
virt-managerをインストールしたときに一緒にインストールされてしまったので、
インストールのコマンドがわかりません・・・
おそらく、
$ sudo apt-get install python-gtk2
こんな感じでインストールできると思います。
import gtkが通ればOKです。
$ python
Python 2.7.2+ (default, Oct 4 2011, 20:03:08)
[GCC 4.6.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import gtk
>>>
gladeのインストールと画面作成
virt-managerがインストールされているフォルダ(/usr/share/virt-manager)を見ると、
「glade」という拡張子のファイルが存在します。
gtkの画面を手書きで作成するのは骨が折れるので、gladeというツールを使用するのが
主流のようです。
http://glade.gnome.org/
インストールは、apt-getで。
$ sudo apt-get install glade
インストール後、Dashで「glade」と入力するとアプリケーションが見つかると思います。

Visual Studioライクな画面なので、なんとかなりそうです。
適当に、ウインドウとボタンを置いてみました。

これを、「sample.glade」というファイル名で保存しました。
内容は、こんなXMLファイルとなるはずです。
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.0 -->
<object class="GtkWindow" id="window1">
<property name="can_focus">False</property>
<property name="has_resize_grip">False</property>
<child>
<object class="GtkFixed" id="fixed1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton" id="button1">
<property name="label" translatable="yes">button</property>
<property name="width_request">100</property>
<property name="height_request">80</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_action_appearance">False</property>
</object>
<packing>
<property name="x">26</property>
<property name="y">26</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
Pythonのコード
画面を表示して、左上の閉じるボタンを押したらプログラムを終了するコードを書いてみます。
- # -*- coding:utf-8 -*-
- import sys
- import gtk
- class GtkGladeSample:
- def __init__(self):
- builder = gtk.Builder()
- #sample.gladeファイルから画面を作成
- builder.add_from_file("sample.glade")
- #windows1というオブジェクトを取得
- self.window = builder.get_object("window1")
- #windows1が破棄される時、testを呼び出す
- self.window.connect("delete-event", self.test)
- self.window.show()
- def test(self, windows, event):
- print('here', windows, event)
- #明示的に終了しないと、Python自体が終了しないっぽい
- sys.exit(0)
- def main(self):
- gtk.main()
- if __name__ == "__main__":
- app = GtkGladeSample()
- app.main()
スクリプトを実行するとこんな画面が表示されるかと。

※まだボタンを押しても無反応です。
左上の閉じるボタンを押すと、こんなメッセージと共にスクリプトが終了すると思います。
('here', <gtk.Window object at 0xb5ed0acc (GtkWindow at 0x915b008)>, <gtk.gdk.Event at 0xb5f0f590: GDK_DELETE>)
とりあえず、起動と終了まで行えました。
地味に、
self.window.connect("delete-event", self.test)
として、閉じるボタンが押された時のイベントを取得する方法がわからず苦労しました。
glade側で閉じるの定義
Pythonのコードで明示的に"delete-event"とself.testの関連付けを行いましたが、
gladeの画面で定義することもできます。
たぶん、こちらの方法が一般的なんだと思います。
windows1を選択した状態で、「シグナル」タブを選択。
GtkWidgetのdelete-eventのハンドラの名前に「test」と入力して保存します。

gladeの定義に埋め込んでおけば、builderが自動的にシグナルとメソッドを連結してくれます。
- # -*- coding:utf-8 -*-
- import sys
- import gtk
- class GtkGladeSample:
- def __init__(self):
- builder = gtk.Builder()
- #sample.gladeファイルから画面を作成
- builder.add_from_file("sample.glade")
- #sample.gladeで定義されているシグナルと連結
- builder.connect_signals(self)
- #windows1というオブジェクトを取得
- self.window = builder.get_object("window1")
- self.window.show()
- def test(self, windows, event):
- print('here', windows, event)
- #明示的に終了しないと、Python自体が終了しないっぽい
- sys.exit(0)
- def main(self):
- gtk.main()
- if __name__ == "__main__":
- app = GtkGladeSample()
- app.main()
はまったポイント
最初、glade定義体の読み込みを
xml = gtk.glade.XML("sample.glade")
としていたのですが、こんなエラーになります。
(sample.py:7459): libglade-WARNING **: Expected <glade-interface>. Got <interface>.
(sample.py:7459): libglade-WARNING **: did not finish in PARSER_FINISH state
こちらを参考に、gtk.Builder()を使用することで解決しました。
Python Glade could not create GladeXML Object
最近はgtk.Builder()を使用するのが主流なのでしょうか?
【参考URL】
PyGTK: GTK+ for Python
http://www.pygtk.org/
gtk.Builder
http://www.pygtk.org/docs/pygtk/class-gtkbuilder.html
Python Glade could not create GladeXML Object
http://stackoverflow.com/questions/2668618/python-glade-could-not-create-gladexml-object
Problems with gtk.Builder and connect_signals (Python)
http://www.gtkforums.com/viewtopic.php?t=1514
PyGTK + Gladeの簡単な例
http://d.hatena.ne.jp/kakurasan/20080522/p1
- 関連記事
コメント