PyGtk+Gladeでカスタムウィジェットを使う

先日の日記で「うまくいかない」と書いたのですが、原因がわかりました。

参考にしていたソースはこちらなんですが、このサンプルではメインウィジェットがSimpleGladeAppというクラスを継承していてその中でやっている処理があったため、シンプルな記述でカスタムウィジェットを使えていたのです。SimpleGladeApp.pyはLGPLのようなのでこれをそのまま利用するという手もありますが、勉強のためにこの中でやっている処理を自分なりに記述してみると、きちんとカスタムウィジェットが使えるようになりました。

というわけで、PyGtkとGladeを使ってカスタムウィジェットを利用する方法は、以下の手順になります。

  • カスタムウィジェットにするクラスを記述する。
  • 配置するウインドウクラス内に生成関数(引数はstr1,str2,int1,int2)を作り、その中で上記クラスのインスタンスを生成する。戻り値としてそのインスタンスを返す。
  • Glade上にカスタムウィジェットを配置し、上記生成関数を指定する。
  • 配置するウインドウクラス内にカスタムハンドラ関数を作り、__init__()内でgtk.glade.set_custom_handlerを使って呼び出す。
  • 以上でカスタムウィジェットは配置されているがデフォルトではshow()されていないのでshow()する。

ソースで書くと以下のようになります。Glade上でwindow1上にcustom1というカスタムクラスを配置し、make_custom1という生成関数を指定しておきます。

import gtk
import gtk.glade

class Window1:
    def __init__(self):
        gtk.glade.set_custom_handler(self.custom_handler)
        self.wtree = gtk.glade.XML("gladetest.glade")
        self.window = self.wtree.get_widget("window1")
        if (self.window):
            self.window.connect("destroy",gtk.main_quit)
        self.custom1 = self.wtree.get_widget("custom1")
        self.custom1.show()

    def make_custom1(self,str1,str2,int1,int2):
        widget = Custom1()
        return widget

    def custom_handler(self,
            glade, function_name, widget_name,
            str1, str2, int1, int2):
        try:
            handler = getattr(self, function_name)
            return handler(str1, str2, int1, int2)
        except AttributeError:
            return None

class Custom1(gtk.TextView):
    def __init__(self):
        gtk.TextView.__init__(self)

def make_custom1(self,str1,str2,int1,int2):
    widget = Custom1()
    return widget

if __name__=="__main__":
    win = Window1()
    gtk.main()