Eine Vielzahl von Beans erstellen: Erstellen Sie wiederverwendbare JavaBeans-Komponenten

In dieser kurzen Serie untersuchen wir die Entwicklung von JavaBeans-Softwarekomponenten. Letztendlich werden die meisten Bohnen in einer Bohnenentwicklungsumgebung manipuliert. Wir befassen uns hier jedoch nur mit den Aspekten des Frameworks auf Quellenebene. Die Entwicklung von JavaBeans - dh die Entwicklung nach der JavaBeans-Spezifikation - bietet mehrere Vorteile:

  • Beans können in visuellen Entwicklungsumgebungen leicht von Benutzern manipuliert werden, die keine technischen Kenntnisse in der Java-Entwicklung auf Quellenebene haben müssen.

  • Aufgrund der Standardschnittstelle sind Beans leicht verteilbar, sodass Komponenten von Drittanbietern einfacher in die Entwicklungsbemühungen integriert werden können.

  • Entwickler können Code, der für ein Projekt entwickelt wurde, problemlos in eine wiederverwendbare Bibliothek von Komponenten übertragen, auf die bei zukünftigen Entwicklungsbemühungen zugegriffen werden kann.

Das Auge des Sturmes

In dem

erster Teil dieser Serie

Wir haben zwei einfache Beans entwickelt: eine nicht visuelle Alarmbohne und eine grafische Bean mit Links- / Rechtspfeil. Beide wurden mit visuellen erweitert

Customizer

und

Bohneninformationen

Klassen. In den Bohnen, die wir diesen Monat behandeln, werden wir keine Customizer anbieten. Stattdessen konzentrieren wir uns darauf, vorhandene Bohnen und Komponenten zu verwenden, um größere, bessere Bohnen herzustellen.

Voraussetzungen

Als Fortsetzung einer zweiteiligen Reihe werde ich davon ausgehen, dass ich mit den in der vorherigen Ausgabe behandelten Themen vertraut bin, einschließlich der ergänzenden Artikel und Ressourcen.

Die Bohnen

Vom Anfang bis zum Ende dieser Serie entwickeln wir die folgenden Bohnen:

AlarmBean Eine nicht grafische Bean, die ein Ereignis nach einer bestimmten Verzögerung auslöst.
ArrowBean

Eine grafische Bean mit Links- / Rechtspfeil.

ProgressBean

Eine grafische Fortschrittsanzeige.

NumberFieldBean

Eine grafische numerische TextFieldBohne mit Rollknöpfen. Diese Bean verwendet die ArrowBean-Bean.

FontChooserBean

Eine grafische Schriftart-Bean. Diese Bean verwendet die NumberFieldBean-Bean.

FontSelectorBean

Eine grafische Bean zur Auswahl von Schriftarten, die die aktuelle Schriftart anzeigt und die Schaltflächen OK / Abbrechen enthält. Diese Bean verwendet die FontChooserBean-Bean.

FontDialogBean

Eine grafische Bean zur Auswahl von Schriftarten, die die Schriftartenauswahl in einem separaten Dialogfeld öffnet. Diese Bean verwendet die FontSelectorBean-Bean.

Wir haben das AlarmBeanund die ArrowBeanBohnen letzten Monat ausführlich besprochen . In dieser Folge werden wir die verbleibenden Bohnen in unterschiedlichen Detaillierungsgraden diskutieren.

Sie fragen sich vielleicht, warum wir drei Font Beans erstellen. Das ultimative Ziel besteht einfach darin, eine Schriftartenauswahl-Bean zu erstellen, die einen Schriftdialog öffnet, wenn der Benutzer auf eine Schaltfläche klickt. Diese Aufgabe gliedert sich ganz natürlich in die drei Beans, die wir erstellen werden: Die erste ist die Benutzeroberfläche für die Auswahl der Schriftarten, die zweite fügt Dialogsteuerelemente und ein Schriftbeispiel hinzu, und die dritte führt eine Schaltfläche zum Öffnen des Dialogfelds ein und enthält die Grundlagen Dialogbehandlungscode.

Ohne Bohnen müssten wir diese Elemente als spezialisierte AWT-Komponenten oder als einzelne monolithische Klasse entwickeln. Mit Bohnen können wir die drei Teile als unabhängige Bohnen entwickeln, die für sich genommen wiederverwendbar sind.

Unser Anwendungsbereich

Wie bei der ersten Folge dieser Serie geht es uns nur um die Beanismen dieser Klassen und nicht um die tatsächlichen Schrauben und Muttern, die sie zum Ticken bringen. Infolgedessen werden wir die Bohnen in Skelettform diskutieren, die Fragmente, die von besonderer Relevanz sind, rot hervorheben und die anderen Details für Sie in Ihrer Freizeit durchlesen. Wir werden uns auch nicht mit den Customizern befassen, die wir bei unserer Erörterung der ersten beiden Bohnen ausführlich behandelt haben.

Überprüfen Sie den vollständigen Quellcode, um die Zwangsarbeit hinter den Bohnen zu sehen.

Erstellen der ProgressBean-Bean

ProgressBean

ist eine einfache Fortschrittsanzeige. Es handelt sich um eine benutzerdefinierte AWT-Komponente, die einen Prozentwert und eine grafische Balkendarstellung dieses Werts anzeigt, wie in der folgenden Abbildung dargestellt. Es werden zwei Eigenschaften angezeigt: der aktuelle und der maximale Balkenwert.

Der aktuelle Wert wird als beobachtbare Eigenschaft angezeigt . Beobachtbare Eigenschaften sind Eigenschaften, deren Änderungen beobachtet werden können. Beobachter werden auf die gleiche Weise wie Ereignis-Listener bei der Bean registriert und benachrichtigt, wenn sich eine Eigenschaft ändert. Einzelne Eigenschaften einer Bohne müssen von der Bohne explizit beobachtbar gemacht werden; Es ist nicht möglich, Änderungen an irgendeiner Eigenschaft einer Bohne zu beobachten.

Diese Bean wird mit den folgenden zwei Klassen implementiert:

  • ProgressBean - Die Hauptbohnenklasse

  • ProgressBeanBeanInfo - Die Bean-Informationsklasse

Klasse ProgressBean

Das

ProgressBean Klasse ist die Haupt-Bean-Klasse, eine einfache benutzerdefinierte AWT-Komponente und eine Java-Bean.

öffentliche Klasse ProgressBean erweitert Komponente ... 

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.

protected Integer oValue = neue Ganzzahl (Wert); protected void fireValueChange () {listeners.firePropertyChange ("Wert", oValue, oValue = neue Ganzzahl (Wert)); }}

Wir rufen diese Methode auf, um Listener über eine Änderung unserer value- Eigenschaft zu informieren . Wir verwenden die firePropertyChange()Methode unserer Liste, um diese Benachrichtigung zu verbreiten. Der erste Parameter ist der Name der Eigenschaft, der mit dem Namen einer exponierten Eigenschaft übereinstimmen sollte. Der zweite Parameter ist der alte Wert der Eigenschaft. und die dritte Eigenschaft ist der neue Wert. Die PropertyChangeSupportKlasse kehrt zurück, ohne etwas zu tun, wenn der alte und der neue Wert identisch sind.

Klasse ProgressBeanBeanInfo

Das

ProgressBeanBeanInfoKlasse beschreibt einfach die ProgressBeanBean und verdeckt alle geerbten Informationen, die wir verdecken möchten.

Erstellen der NumberFieldBean-Bean

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 () ... 

Hier, setzen wir die intEigenschaften Spalten , Minimum , Maximum , und Schritt , die sind jeweils die Anzahl der Spalten in der Anzeige TextField, die Minimal- und Maximalwerte , dass dieses Feld halten sollte, und der Betrag , um den die Pfeiltasten , sollte das ändern Wert. Diese Eigenschaften sind nicht beobachtbar.

Beachten Sie, dass wir die Synchronisation verwenden, um gegebenenfalls die Thread-Sicherheit zu gewährleisten.

public synchronized void actionPerformed (ActionEvent e) {int value = getValue (); if (e.getSource () == down) {if (Wert> Minimum) {Wert = (Wert - Schritt> Wert)? Minimum: Klemme (Wert - Schritt); setValue (Wert); }} ...