Beanの群れを構築する:再利用可能なJavaBeansコンポーネントを作成する

この短いシリーズでは、JavaBeansソフトウェアコンポーネントの開発について検討します。最終的に、ほとんどのBeanはBean開発環境で操作されます。ただし、ここではフレームワークのソースレベルの側面のみに関心があります。JavaBeansを開発すること、つまりJavaBeans仕様に合わせて開発することの利点は、いくつかあります。

  • Beanは、ソースレベルのJava開発に技術的なスキルを必要としないユーザーが、ビジュアル開発環境で簡単に操作できます。

  • 標準のインターフェースにより、Beanは容易に配布可能であり、サードパーティのコンポーネントを開発作業に簡単に統合できます。

  • 開発者は、1つのプロジェクト用に開発されたコードを、コンポーネントの再利用可能なライブラリに簡単に転送できます。このライブラリには、将来の開発作業でアクセスできます。

嵐の目

の中に

このシリーズの最初の部分

、2つの単純なBeanを開発しました。非視覚的なアラームBeanとグラフィカルな左矢印/右矢印Beanです。両方ともビジュアルで補強されました

カスタマイザー

そして

豆情報

クラス。今月取り上げるBeanでは、カスタマイザーは提供しません。代わりに、既存のBeanとコンポーネントを使用して、より大きく、より優れたBeanを作成することに集中します。

前提条件

2部構成のシリーズの続きとして、補足記事やリソースを含め、前回の記事で説明した問題に精通していることを前提としています。

このシリーズの最初から最後まで、次のBeanを開発しています。

AlarmBean 指定された遅延の後にイベントを発生させる非グラフィカルBean。
ArrowBean

グラフィカルな左矢印/右矢印Bean。

ProgressBean

グラフィカルな進行状況表示Bean。

NumberFieldBean

TextFieldロールボタン付きのグラフィカルな数値Bean。このBeanはArrowBeanBeanを利用します。

FontChooserBean

グラフィカルなフォント選択Bean。このBeanは、NumberFieldBeanBeanを利用します。

FontSelectorBean

現在のフォントを表示し、[OK] / [キャンセル]ボタンを提供するグラフィカルフォント選択Bean。このBeanは、FontChooserBeanBeanを利用します。

FontDialogBean

別のダイアログでフォントセレクターをポップアップするグラフィカルフォントチューザーBean。このBeanは、FontSelectorBeanBeanを利用します。

先月、AlarmBeanArrowBeanBeansについて詳しく説明しました。このエピソードでは、残りのBeanについてさまざまな詳細レベルで説明します。

なぜ3つのフォントBeanを構築しているのか不思議に思うかもしれません。最終的な目標は、ユーザーがボタンをクリックしたときにフォントダイアログをポップアップするフォントセレクターBeanを作成することです。このタスクは、非常に自然に、生成する3つのBeanに分割されます。1つ目はフォント選択用のユーザーインターフェイス、2つ目はダイアログコントロールとフォントサンプルを追加し、3つ目はダイアログをポップアップするボタンを導入して基本的なものを含みますダイアログ処理コード。

Beanがなければ、これらのアイテムを特殊なAWTコンポーネントとして、または単一のモノリシッククラスとして開発する必要があります。Beanを使用すると、3つの部分を、それ自体で再利用可能な独立したBeanとして開発できます。

私たちのスコープ

このシリーズの最初の記事と同様に、これらのクラスのビーニズムのみに関心があり、それらをカチカチ音をたてる実際の要点には関心がありません。その結果、私たちは骨格の形で豆について議論し、特に関連性のある断片を赤で強調表示し、他の詳細をあなたが暇なときに熟読できるように残します。また、最初の2つのBeanの説明で十分に詳細に説明したカスタマイザーについても気にしません。

Beanの背後にある強制労働を確認するには、完全なソースコードを確認してください。

ProgressBeanBeanの構築

ProgressBean

単純な進行状況表示Beanです。これは、次の図に示すように、パーセンテージ値とこの値のグラフィカルなバー表現を表示するカスタムAWTコンポーネントです。現在のバー値と最大バー値の2つのプロパティを公開します。

現在の値は、監視可能なプロパティとして公開されます。観察可能なプロパティは、変化を観察できるプロパティです。オブザーバーは、イベントリスナーと同じ方法でBeanに登録され、プロパティが変更されるたびに通知されます。Beanの個々のプロパティは、Beanによって明示的に観察可能にする必要があります。Beanのプロパティだけの変化を観察することはできません。

このBeanは、次の2つのクラスで実装されます。

  • ProgressBean -メインのBeanクラス

  • ProgressBeanBeanInfo -Bean情報クラス

クラスProgressBean

ザ・

ProgressBean クラスはメインのBeanクラスであり、単純なカスタムAWTコンポーネントとJavaBeanです。

パブリッククラスProgressBeanはComponent ..を拡張します。 

This bean is a lightweight component, so we extend Component instead of Canvas, and provide an appropriate paint() method. The lightweight component framework is more efficient than the traditional custom-component framework, requiring fewer resources of the local windowing system. As a component, we automatically inherit the serializability mandated by JavaBeans, and we provide the default no-arg constructor.

public void setBarground (Color c) ... public Color getBarground () ... public synchronized void setMaximum (int m) ... public int getMaximum () ... 

Here, we expose the Color property barground (the color of the displayed bar) and the int property maximum (the maximum bar value).

public synchronized void setValue (int v) { if (value != v) { value = v; repaint (); fireValueChange (); } } public int getValue () ... 

The int property value is observable, which means that we must inform all interested listeners whenever its value changes. To this end, we call our fireValueChange() method to inform the listeners whenever setValue() is called.

protected PropertyChangeSupport listeners = new PropertyChangeSupport (this); public void addPropertyChangeListener (PropertyChangeListener l) { listeners.addPropertyChangeListener (l); } public void removePropertyChangeListener (PropertyChangeListener l) { listeners.removePropertyChangeListener (l); } 

Here, we maintain a list of objects that are registered to be notified whenever an observable property changes. We use the class PropertyChangeSupport from the java.beans package to maintain this list. The constructor for this class requires us to specify the bean that will be the origin of property change events; in this case, it is this, and the methods that it provides allow us to maintain the list.

By exposing the methods addPropertyChangeListener() and removePropertyChangeListener(), we automatically indicate that this bean has observable properties. We do not, however, indicate which properties are observable. That information must be appropriately documented with the bean.

保護された整数oValue =新しい整数(値); protected void fireValueChange(){listeners.firePropertyChange( "value"、oValue、oValue = new Integer(value)); }

このメソッドを呼び出して、valueプロパティの変更をリスナーに通知します。firePropertyChange()リストのメソッドを使用して、この通知を伝達します。最初のパラメーターはプロパティの名前であり、公開されたプロパティの名前と一致する必要があります。2番目のパラメーターは、プロパティの古い値です。3番目のプロパティは新しい値です。PropertyChangeSupport古い値と新しい値が同じであれば何もせずにクラスを返します。

クラスProgressBeanBeanInfo

ザ・

ProgressBeanBeanInfoクラスは単にProgressBeanBeanを記述し 、隠したい継承情報を隠します。

NumberFieldBeanBeanの構築

This bean implements a common user-interface component, the rollable number entry field -- a numeric text field that provides increment and decrement arrows, as shown in the figure below. This bean brings up an important JavaBeans concept:

programmatic manipulation of beans

.

Programmatic manipulation of beans refers to the mechanisms that JavaBeans provides for programmatically creating and accessing beans. Although it is possible to access beans using the standard Java object creation (new X ()) and type-casting mechanisms ((Y) x), it is recommended that you use the provided JavaBeans mechanisms to allow for future extension of the JavaBeans framework.

This bean is implemented with the following two classes:

  • NumberFieldBean -- The main bean class

  • NumberFieldBeanBeanInfo -- The bean information class

Class NumberFieldBean

The NumberFieldBean class, the main bean class, is an AWT container that adds three components: two ArrowBean beans and a TextField. Programmatic access to the ArrowBean class requires that we make use of the bean manipulation mechanisms I mentioned a moment ago.

The current numeric value is exposed as an observable property. Although it is a normal property that can be accessed and manipulated through the usual beans accessor methods, it is also observable, so listeners can register to be notified whenever its value changes. We do not fire an event when the user presses Return, although that would be an obvious extension to this class.

public class NumberFieldBean extends Container implements ActionListener ... 

We extend Container and implement ActionListener in order to receive events from the beans and AWT components that we use. Extending Container instead of the more traditional Panel means that this bean, like the ProgressBean bean is a lightweight component.

public NumberFieldBean () ... 

As a bean, we must provide a public no-arg constructor. Note that we should not provide other constructors for programmatic use; doing so would go against the JavaBeans access mechanism.

try { down = (ArrowBean) Beans.instantiate (getClass ().getClassLoader (), "org.merlin.beans.arrow.ArrowBean"); } catch (Exception ex) { ex.printStackTrace (); } 

Here, we create an ArrowBean using the programmatic beans instantiation mechanism. We don't use the standard Java new operator; instead, we use the instantiate() method of class Beans. We specify the ClassLoader to use for loading the bean class; in this case, we use our own ClassLoader and the fully qualified name of the bean class ("org.merlin.beans.arrow.ArrowBean"), and cast the resulting Object to the appropriate class.

Note that the instantiate() method may throw a variety of exceptions (for example, if the specified bean could not be located). We simply catch and display any such exceptions, which, by the way, should not occur if the bean is appropriately installed.

add ("East", (Component) Beans.getInstanceOf (down, Component.class)); 

Here, we cast the ArrowBean to a Component and add it as a normal Component. We don't use the standard (Component) type-casting mechanism, and we don't use the fact that our AlarmBean is a subclass of Component; instead, we use the getInstanceOf() method of class Beans. We specify the bean that we wish to cast and the Class object to which we wish to cast it (in this case, Component.class).

Although this approach makes little sense right now, future versions of JavaBeans will support beans composed of multiple class files, as well as beans that can expose different aspects of themselves as the different classes. For example, a bean could appear to subclass both Component and RemoteObject by providing two coupled classes: a Component and a RemoteObject. Using the JavaBeans type-casting mechanism, the appropriate bean object can be returned automatically, so beans can have apparent multiple-inheritance, although Java does not natively support this. For details, see the "Glasgow" JavaBeans specification. (A link to this spec is provided in the Resources section of this article.)

It is necessary for us to use these beans access mechanisms now, so we can transition our beans to future JavaBeans technologies without any problems.

down.setDirection (ArrowBean.LEFT); down.addActionListener (this); 

Here, we configure the ArrowBean using the setDirection() property accessor and the addActionListener() registration method. We can use these property accessors and listener registration methods directly on the bean we just created; it is only necessary to use the JavaBeans type-casting feature when we are accessing an aspect of a bean that is inherited from another class.

public synchronized void setValue (int v) { field.setText (String.valueOf (v)); fireValueChange (getValue ()); } public synchronized int getValue () ... 

Here, we expose the int property value, which is the value of this field. This property is observable, so we must notify listeners whenever it is changed. We do this by calling our fireValueChange() method.

public void setColumns (int c) ... public int getColumns () ... public synchronized void setMinimum (int m) ... public int getMinimum () ... public synchronized void setMaximum (int m) ... public int getMaximum () ... public synchronized void setStep (int s) ... public int getStep () ... 

ここでは、intプロパティminimummaximum、およびstepを公​​開します。これらはそれぞれ、に表示される列の数、TextFieldこのフィールドが保持する必要のある最小値と最大値、および矢印ボタンが変更する必要のある量です。値。これらの特性は観察できません。

必要に応じて、同期を使用してスレッドセーフを確保することに注意してください。

public synchronized void actionPerformed(ActionEvent e){int value = getValue(); if(e.getSource()== down){if(value> minimum){value =(value-step> value)?最小:クランプ(値-ステップ); setValue(値); }}..。