next up previous contents
Next: PropertyEditorSupport Up: Property Editor Previous: Property Editor

PropertySheetは、どのように作られるか?

BeanBox内でフォーカスを得たBeanクラスのプロパティが、プロパティ・シートに どのように表示されるのかを見てみましょう。

まず、そのBeanクラスのBeanInfoが作られます。ここでは、すぐ前で名前の出た IntrospectorクラスのsetTargetPropertyInfo()メソッドが活躍しています。 さらに、このBeanInfoのインスタンスから、PropertyDescriptor の配列を獲得します。 何か、まどろっこしいように感じるかも知れませんが、Beanクラスから、まず、 BeanInfoを作って、それから様々なDescriptorを獲得するというのは、Java Beans プログラミングの基本的なイディオムです。

一つのBeanクラスには、一般に複数のプロパティが存在します。PropertySheetPanelの setTargetメソッドは、ターゲットとなるbeanの一つ一つのPropertyに対して、それ ぞれのsetter / getterメソッドを獲得して、先に見た reflectionの機能を利用して、 getter.invoke(target, args)で、ターゲット上のそのプロパティの値を獲得します。 そして、プロパティの型に対応したeditorをつくって、editor.setValue(value) で、プロパティの値をeditorにセットします。setTagetメソッドは、この処理を、 プロパティの数だけ繰り返します。このように、Java Beansでは、一つのプロパティに 一つのeditorが対応しています。プロパティ・シート全体を、一つのeditorと考える こともできるのですが、正確に言うと、プロパティ・シートは、沢山のeditor達が 集まって出来ているのです。

============================================================================
class PropertySheetPanel extends Panel {
 .......
    synchronized void setTarget(Object targ) {
        ........
        ........
        target = targ; 
        try {
        // フォーカスが当てられたbeanクラスから BeanInfoを作成し、
        // そのBeanInfoからPropertyDescriptor の配列を獲得する。
            BeanInfo bi = Introspector.getBeanInfo(target.getClass()); 
            properties = bi.getPropertyDescriptors();
        } catch (IntrospectionException ex) {
           ........           
        }
        // Propertyの数の分だけ、それぞれの配列を準備する。
        editors = new PropertyEditor[properties.length];
        values = new Object[properties.length];
        ........
        // adapterは、PropertyChangeListener を実装
        EditedAdaptor adaptor = new EditedAdaptor(frame);

        // Propertyの数だけ、その値を表示する。
        for (int i = 0; i < properties.length; i++) {
            .......
            Method getter = properties[i].getReadMethod();  // getterの獲得。
            Method setter = properties[i].getWriteMethod(); // setterの獲得。
            .......
            try {
                Object args[] = { };
                // 注目 !!  target上でのgetterの呼び出し。すなわち、値の獲得。
                Object value = getter.invoke(target, args);
                values[i] = value;
                PropertyEditor editor = null;
                Class pec = properties[i].getPropertyEditorClass();
                if (pec != null) {
                    try {
                // PropertyEditorClassのインスタンスの作成 = editorの作成
                        editor = (PropertyEditor)pec.newInstance();
                    } catch (Exception ex) {
                    }
                }
                if (editor == null) {
                    // 駄目なら、別の方法でeditorを作る。
                    editor = PropertyEditorManager.findEditor(type);
                }
                editors[i] = editor;
                ..........
                // editorに値を設定する。
                editor.setValue(value);
                // adaptorは、editorの リスナーになる。
                editor.addPropertyChangeListener(adaptor);
                ..........
            } catch (Exception ex) {
                ..........
            }
        .......
        }
        .......
    }
 .......
}
============================================================================

このsetTargetメソッドは、BeanBox内のあるBeanに新しいフォーカスが置かれた時 に最初に呼び出されて、そのプロパティの値を読み出して PropertySheetを形成 するのが主な仕事ですが、もう一つ、大事な役割を担っています。 それは、後で見る editorでのプロパティの値の変更を、BeanBox内のbeanに反映するための仕掛けを準備 することです。setTargetは、ターゲットとなる一つのbeanに対して、 EditedAdaptorクラスのオブジェクトを一つ用意します。そして、そのbeanに属する 一つ一つのプロパティのeditorが、このadapterオブジェクトを、それぞれの PropertyChangeEvent の Listenerとして登録するようにします。for文の中で、 editor.addPropertyChangeListener(adaptor) が繰り返されているのは、その為です 一つのbeanには複数のeditor達が関連付けられるのですが、これらが集まった同じ PropertySheet上で発生した PropertyChangeEventは、すべて、いったん、このadaptor に集められるということです。



maruyama@wakhok.ac.jp