Python + gtk + gladeでGUIアプリケーションの作成 その1

KVMをリモートで管理するため、virt-managerというアプリケーションを使用しました。
UbuntuからリモートサーバーのKVMに接続し、仮想OSをインストールする

virt-manager、ソースを見てみるとPythonで書かれています。
こんなGUIアプリケーションがPythonで作れるとは。

38_001.png


自分でも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」と入力するとアプリケーションが見つかると思います。
38_002.png


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


これを、「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のコード



画面を表示して、左上の閉じるボタンを押したらプログラムを終了するコードを書いてみます。


  1. # -*- coding:utf-8 -*-
  2. import sys
  3. import gtk
  4. class GtkGladeSample:
  5.     
  6.     def __init__(self):
  7.         builder = gtk.Builder()
  8.         #sample.gladeファイルから画面を作成
  9.         builder.add_from_file("sample.glade")
  10.         
  11.         #windows1というオブジェクトを取得
  12.         self.window = builder.get_object("window1")
  13.         #windows1が破棄される時、testを呼び出す
  14.         self.window.connect("delete-event", self.test)
  15.         self.window.show()
  16.     def test(self, windows, event):
  17.         print('here', windows, event)
  18.         #明示的に終了しないと、Python自体が終了しないっぽい
  19.         sys.exit(0)
  20.     def main(self):
  21.         gtk.main()
  22. if __name__ == "__main__":
  23.     app = GtkGladeSample()
  24.     app.main()




スクリプトを実行するとこんな画面が表示されるかと。
38_004.png

※まだボタンを押しても無反応です。


左上の閉じるボタンを押すと、こんなメッセージと共にスクリプトが終了すると思います。

('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」と入力して保存します。
38_005.png


gladeの定義に埋め込んでおけば、builderが自動的にシグナルとメソッドを連結してくれます。

  1. # -*- coding:utf-8 -*-
  2. import sys
  3. import gtk
  4. class GtkGladeSample:
  5.     
  6.     def __init__(self):
  7.         builder = gtk.Builder()
  8.         #sample.gladeファイルから画面を作成
  9.         builder.add_from_file("sample.glade")
  10.         #sample.gladeで定義されているシグナルと連結
  11.         builder.connect_signals(self)
  12.         
  13.         #windows1というオブジェクトを取得
  14.         self.window = builder.get_object("window1")
  15.         self.window.show()
  16.     def test(self, windows, event):
  17.         print('here', windows, event)
  18.         #明示的に終了しないと、Python自体が終了しないっぽい
  19.         sys.exit(0)
  20.     def main(self):
  21.         gtk.main()
  22. if __name__ == "__main__":
  23.     app = GtkGladeSample()
  24.     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





関連記事

コメント

プロフィール

Author:symfo
blog形式だと探しにくいので、まとめサイト作成中です。
https://symfo.web.fc2.com/

PR

検索フォーム

月別アーカイブ