では、次に複数の同じアイテム(部品)が並んだ場合、イベントが発生したときにそれらを区別するにはどうしたら良いのでしょうか? 例えば数値入力ボックスが複数並んだケースを考えます。この数値入力ボックスに値を入れたり、変更すると、メッセージボックスが現れ、入力数値を表示するというサンプルプログラムです。
結局、これはどのように対処するかというと、各数値入力ボックスに掛けるプレビューア・クラスは同一でも、各入力ボックス毎に別々のプレビューアのインスタンスを作って掛けることになります。別々のインスタンスを掛けることで入力ボックスの区別を行ってイベントに対応した動作を実行します。
----------------
# Interactive UI sample with event listeners from ij import IJ, ImagePlus from ij.gui import GenericDialog from java.awt.event import TextListener class DialogPreviewer(TextListener): def __init__(self, nfield, index): """ nfield: a java.awt.TextField """ self.nfield = nfield self.index = index def textValueChanged(self, event): textStrings = self.nfield.getText() print "Text Changed", textStrings # print textStrings try: value = int(textStrings) IJ.showMessage("Input numeric" + str(self.index) + ": " + str(value)) except: return def testImageUI(): gd = GenericDialog("interactive generic dialog test") gd.addNumericField("Input numeric0", 0.0) gd.addNumericField("Input numeric1", 0.0) gd.addNumericField("Input numeric2", 0.0) gd.addNumericField("Input numeric3", 0.0) # The UI elements for the above two inputs nfields = [] previewers = [] for i in range(4): print i nfields.append(gd.getNumericFields().get(i)) previewers.append(DialogPreviewer(nfields[i], i)) nfields[i].addTextListener(previewers[i]) gd.showDialog() if gd.wasCanceled(): print "User canceled dialog!" testImageUI() ----------------
プログラムの解説です。
まず冒頭で必要な各ライブラリを読み込みます。ここではJava のテキストリスナーを使いますので、
from java.awt.event import TextListener
を読み込んでおきます。
次に、クラス、DialogPreviewer を定義します。このプレビューアはテキストリスナーを使いますので、引数に入れておきます。そしてコンストラクタでこのクラスが使う引数を定義します。self 以外に、nfield (入力ボックス)と index (ボックスのインデックス番号) を引数として定義します。
そしてテキストリスナーの唯一のイベント、textValueChanged に対応したメソッドを定義しています。入力ボックスの文字が変更されたら、入力ボックスから、textStrings という変数にボックスの内容を文字列として取得します。
そして、この文字列を整数に直し、メッセージボックスに、入力ボックスのインデックス番号と、変更された値を表示します。もし整数化に失敗した場合は、何も行わず return で戻ります。
最後にダイアログボックスの定義です。4つ、Numeric Field を配置し、その後に、for ループを使って、イベントリスナーを各ボックス毎に設置します。
previewers.append(DialogPreviewer(nfields[i], i))
の文で、入力ボックス毎にDialogPreviewerのインスタンスを、previewers[0], previewers[1]... というように別々に定義し、各ボックス毎に別々のインスタンスを設置しています。
なお、アイテムを配列化したもの (ここの例で言えば nfields) にまとめてイベントリスナーを設置することはできません。必ず部品一つ一つにイベントリスナーを設置する必要があります。
また、異なるアイテムであれば、同一のインスタンスの、イベントプレビューアを実装したプレビューアの中に複数のアイテムを共存させることはできますが、同一の種類の複数のアイテムを同一のインスタンスの中に入れると、動作はするはするのですが、余計な回数のイベントが発生してしまいます。余計な回数の動作を避けるためには、プレビューアに対しアイテムごとにインデックス番号を指定して異なったインスタンスとして掛けることが必要です。
また、同一の部品 (アイテム) に複数のイベントリスナーを掛けてはいけません。動作が不定になります。
ーーーーーーーーー