試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

PyGTK + Gladeのアプリケーションにおけるハンドラ関数について(後半)

PyGTK + Gladeのアプリケーションにおけるハンドラ関数について(前半)」の続き。

ユーザ・データについて

Gladeでは、シグナルの設定のところにユーザ・データを指定することができる。しかし、PyGTK + Gladeでは、Gladeの「ユーザ・データ」に値を指定しても、うまく処理されないように見える(gtk.gladeの仕様?)。例として、「PyGTK + Gladeの簡単な例」のgladeファイルをもとに、「button1」のシグナル「clicked」のユーザ・データを何か入れて上書き保存して、コード側のon_button1_clicked()を下のように書き換えた場合

  def on_button1_clicked(self, widget, user_data):
    """
    ボタンが押されたときの処理
    """
    print "on_button1_clicked(user_data:%s)" % user_data

これを実行してボタンをクリックすると

TypeError: on_button1_clicked() takes exactly 3 arguments (2 given)

となってしまう。
手動(gobject.GObject.connect()(リファレンス))でデータを渡したときにはうまくいくようだ。「PyGTK + Gladeの簡単な例」のgladeファイルの「button1」に関するシグナル設定を解除して、代わりに、__init__()

  def __init__(self):
    """
    初期化処理
    """
    gladefile = os.path.dirname(__file__) + "/pygtkgladetest.glade"
    xml = gtk.glade.XML(gladefile)
    xml.signal_autoconnect(self)
    signal_dic = { "gtk_main_quit" : gtk.main_quit }
    xml.signal_autoconnect(signal_dic)
    self.window = xml.get_widget("window1")
    # 追加
    self.button = xml.get_widget("button1")
    self.button.connect("clicked", self.on_button1_clicked, "Test")
    self.window.show_all()

とした場合、ボタンクリック時には

on_button1_clicked(user_data:Test)

と表示され、正常にユーザ・データが処理されていることが分かる。

どこにある関数が呼ばれるか

あるクラスの中でgtk.glade.XMLオブジェクトを作成し、signal_autoconnect()に「self」を渡してシグナル接続を行った場合、ハンドラに指定された名前を持った同じクラスのメンバ関数が使用される。
gobject.GObject.connect()により手動でシグナル接続を行う場合には、クラスの外部にある関数を指定することもできる。

#! /usr/bin/python
# -*- encoding: utf-8 -*-

import sys
import os
try:
  import pygtk
  pygtk.require("2.0")
except:
  pass
try:
  import gtk
  import gtk.glade
except:
  sys.exit(1)


def on_button1_clicked(widget, user_data):
  print "FUNCTION on_button1_clicked(user_data:%s)" % user_data

class PyGTKGladeTest:
  def __init__(self):
    gladefile = os.path.dirname(__file__) + "/pygtkgladetest.glade"
    xml = gtk.glade.XML(gladefile)
    xml.signal_autoconnect(self)
    signal_dic = { "gtk_main_quit" : gtk.main_quit }
    xml.signal_autoconnect(signal_dic)
    self.window = xml.get_widget("window1")
    self.button = xml.get_widget("button1")
    self.button.connect("clicked", on_button1_clicked, "Test")
    self.window.show_all()
  def on_button1_clicked(self, widget, user_data):
    print "METHOD on_button1_clicked(user_data:%s)" % user_data
  def on_imagemenuitem1_select(self, widget):
    print "on_imagemenuitem1_select"
  def on_imagemenuitem1_deselect(self, widget):
    print "on_imagemenuitem1_deselect"
  def main(self):
    gtk.main()

if __name__ == "__main__":
  app = PyGTKGladeTest()
  app.main()

これを実行してボタンをクリックすると、関数on_button1_clicked()が実行され、

FUNCTION on_button1_clicked(user_data:Test)

と表示される。もし、connect()

    self.button.connect("clicked", self.on_button1_clicked, "Test")

と指定すると、クラスのメンバ関数on_button1_clicked()が実行され、

METHOD on_button1_clicked(user_data:Test)

と表示される。

関連記事:

使用したバージョン:

  • PyGTK 2.12.0
  • Glade 3.4.4