GtkBuilderとGladeについてと、PyGTK上での使用について(実際のコード・後半)
「GtkBuilderとGladeについてと、PyGTK上での使用について(実際のコード・前半)」の続き。
メニュー項目の選択と選択解除のシグナル(select/deselect)は使えない?
#! /usr/bin/python # -*- encoding: utf-8 -*- import sys import os try: import pygtk pygtk.require("2.0") except: pass try: import gtk except: print >> sys.stderr, "Error: PyGTK not installed" sys.exit(1) if gtk.pygtk_version < (2,12,0): errtitle = "Error" errmsg = "PyGTK 2.12.0 or later required" if gtk.pygtk_version < (2,4,0): print >> sys.stderr, errtitle + ": " + errmsg else: errdlg = gtk.MessageDialog(type=gtk.MESSAGE_ERROR, buttons = gtk.BUTTONS_OK) errdlg.set_title(errtitle) errdlg.set_markup(errmsg) errdlg.run() sys.exit(1) class PyGTKBuilderTest: """ テスト """ def __init__(self): """ 初期化処理 """ # uiファイル(同じディレクトリのpygtkbuildertest.ui)を読み込む uifile = os.path.dirname(__file__) + "/pygtkbuildertest.ui" xml = gtk.Builder() xml.add_from_file(uifile) # uiファイルで定義されているシグナルを自動で接続 #xml.connect_signals(self) # ハンドラ「gtk_main_quit」は別途「gtk.main_quit()」に設定 # インスタンス指定と辞書指定はどちらか一方しかできない? # 先に実行したほうだけが有効になっているような感じ signal_dic = { "on_button1_clicked" : self.on_button1_clicked, "gtk_main_quit" : gtk.main_quit } xml.connect_signals(signal_dic) # 個別のウィジェットをXMLから取り出す self.window = xml.get_object("window1") self.imagemenuitem1 = xml.get_object("imagemenuitem1") # 手動でシグナル接続 self.window.connect("delete_event", gtk.main_quit) # 下の2つは「unknown signal name」でダメ # (GtkActionになっていてGtkMenuItemではない) self.imagemenuitem1.connect("select", self.on_imagemenuitem1_select) self.imagemenuitem1.connect("deselect", self.on_imagemenuitem1_deselect) # 表示 self.window.show_all() def on_button1_clicked(self, widget): """ ボタンが押されたときの処理 """ print "on_button1_clicked" def on_imagemenuitem1_select(self, widget): """ メニュー項目が選択されたときの処理(呼ばれない) """ print "on_imagemenuitem1_select" def on_imagemenuitem1_deselect(self, widget): """ メニュー項目が選択解除されたときの処理(呼ばれない) """ print "on_imagemenuitem1_deselect" def main(self): """ GTK+のメインループを呼ぶ """ gtk.main() if __name__ == "__main__": app = PyGTKBuilderTest() app.main()
今度はメニュー項目に相当するGUI部品(ウィジェット)を取り出した後、gobject.GObjectオブジェクトのメンバ関数connect()(リファレンス)を使用して、手動でシグナル接続を試みたのだが
Traceback (most recent call last): File "[スクリプトの場所]", line 81, in ? app = PyGTKBuilderTest() File "[スクリプトの場所]", line 55, in __init__ self.imagemenuitem1.connect("select", self.on_imagemenuitem1_select) TypeError: <gtk.Action object at 0x7fbc26cf2e60 (GtkAction at 0x839930)>: unknown signal name: select
のようになってダメだった。エラーが示すのは、gtk.Actionオブジェクトには「select」(「deselect」も同様)というシグナルはないということで、これは正しい。
gladeファイルを使用した場合、メニュー項目というウィジェットはgtk.Itemから派生したクラスになるため、これらのシグナルが扱えるのだが、uiファイル/gtk.Builderを使用する場合、gtk-builder-convertでgladeファイルから変換するときにgtk.Actionにされてしまうため、使えなくなってしまうようだ(恐らくは仕様)。
動作する最小限サンプル
動作する形としては、下のような形に落ち着いた。gladeファイルを使用したときよりもできることが減ってしまった。
#! /usr/bin/python # -*- encoding: utf-8 -*- import sys import os try: import pygtk pygtk.require("2.0") except: pass try: import gtk except: print >> sys.stderr, "Error: PyGTK not installed" sys.exit(1) if gtk.pygtk_version < (2,12,0): errtitle = "Error" errmsg = "PyGTK 2.12.0 or later required" if gtk.pygtk_version < (2,4,0): print >> sys.stderr, errtitle + ": " + errmsg else: errdlg = gtk.MessageDialog(type=gtk.MESSAGE_ERROR, buttons = gtk.BUTTONS_OK) errdlg.set_title(errtitle) errdlg.set_markup(errmsg) errdlg.run() sys.exit(1) class PyGTKBuilderTest: """ テスト """ def __init__(self): """ 初期化処理 """ # uiファイル(同じディレクトリのpygtkbuildertest.ui)を読み込む uifile = os.path.dirname(__file__) + "/pygtkbuildertest.ui" xml = gtk.Builder() xml.add_from_file(uifile) # uiファイルで定義されているシグナルを自動で接続 #xml.connect_signals(self) # ハンドラ「gtk_main_quit」は別途「gtk.main_quit()」に設定 # インスタンス指定と辞書指定はどちらか一方しかできない? # 先に実行したほうだけが有効になっているような感じ signal_dic = { "on_button1_clicked" : self.on_button1_clicked, "gtk_main_quit" : gtk.main_quit } xml.connect_signals(signal_dic) # 個別のウィジェットをXMLから取り出す self.window = xml.get_object("window1") # 手動でシグナル接続 self.window.connect("delete_event", gtk.main_quit) # 表示 self.window.show_all() def on_button1_clicked(self, widget): """ ボタンが押されたときの処理 """ print "on_button1_clicked" def main(self): """ GTK+のメインループを呼ぶ """ gtk.main() if __name__ == "__main__": app = PyGTKBuilderTest() app.main()
関連記事:
- PyGTK + Gladeの簡単な例
- GtkBuilderとGladeについてと、PyGTK上での使用について(概要)
- GtkBuilderとGladeについてと、PyGTK上での使用について(実際のコード・前半)
- PyGTKの簡単な例をPythonのコードのみで書く
- PyGTKでGtkBuilderをレイアウトに用いながらGUI部品のクラスを継承
参考URL:
使用したバージョン:
- GTK+ 2.12.9(2.12.9-r2)
- PyGTK 2.12.0
- Glade 3.4.4