From 33613a85afc4b1481367fbe92a17ee59c240250b Mon Sep 17 00:00:00 2001 From: Sven Eisenhauer Date: Fri, 10 Nov 2023 15:11:48 +0100 Subject: add new repo --- .../hjp5/html/k100285.html | 874 +++++++++++++++++++++ 1 file changed, 874 insertions(+) create mode 100644 Master/Reference Architectures and Patterns/hjp5/html/k100285.html (limited to 'Master/Reference Architectures and Patterns/hjp5/html/k100285.html') diff --git a/Master/Reference Architectures and Patterns/hjp5/html/k100285.html b/Master/Reference Architectures and Patterns/hjp5/html/k100285.html new file mode 100644 index 0000000..ce54a9b --- /dev/null +++ b/Master/Reference Architectures and Patterns/hjp5/html/k100285.html @@ -0,0 +1,874 @@ + + + +Handbuch der Java-Programmierung, 5. Auflage + + + + + + + + + +
 Titel  + Inhalt  + Suchen  + Index  + DOC  +Handbuch der Java-Programmierung, 5. Auflage +
 <<  +  <   +  >   + >>  + API  +Kapitel 44 - Beans +
+
+ + + + +

44.6 BeanInfo-Klassen und Property-Editoren

+
+ +
+ + + + +

44.6.1 BeanInfo-Klassen

+ +

+Die bisher beschriebenen Fähigkeiten und Eigenschaften einer +Bean wurden vom GUI-Designer automatisch erkannt, weil die Beans bestimmte +Design-Konventionen eingehalten haben. Der GUI-Designer verwendet +eine Instanz der Klasse Introspector +aus dem Paket java.beans, +um diese Fähigkeiten nach dem Laden der Bean zu bestimmen. + +

+Neben getter-/setter-Methoden und Registrierungsmethoden für +Events können Beans aber noch weitere Eigenschaften besitzen. +So kann beispielsweise in der Toolbox ein Icon angezeigt werden. Auch +Methoden, die nicht den getter-/setter-Konventionen entsprechen, können +bekanntgemacht werden. Zudem ist es möglich, für Nicht-Standard-Eigenschaften +spezielle Eigenschafteneditoren zur Verfügung zu stellen. + +

+Diese Möglichkeiten stehen erst zur Verfügung, wenn man +die Bean mit einer expliziten BeanInfo-Klasse +ausstattet. Sie hat denselben Namen wie die Bean, trägt aber +zusätzlich den Suffix »BeanInfo« am Ende ihres Namens. +Zudem muss sie im selben Paket liegen wie die Bean-Klasse. Die BeanInfo-Klasse +muss das Interface BeanInfo +implementieren oder aus SimpleBeanInfo +abgeleitet sein (letzteres bietet den Vorteil, dass bereits alle erforderlichen +Methoden vorhanden sind und bei Bedarf nur noch überlagert werden +müssen). + +

+BeanInfo +definiert eine Reihe von Methoden, die der GUI-Designer abfragt. Sie +liefern jeweils ein Array von Descriptor-Objekten, von denen jedes +Informationen über eine zu veröffentlichende Methode, Eigenschaft +oder ein Icon zur Verfügung stellt. Wir wollen uns die drei wichigsten +von ihnen in den nachfolgenden Abschnitten ansehen. +

+ + + + + + + + + + + +
+ +

+Während der GUI-Designer die ihm bekannten Beans lädt, sucht +er für jede von ihnen zunächst nach einer passenden BeanInfo-Klasse. +Findet er eine solche, wird sie verwendet, und der Low-Level-Introspectionsvorgang +wird gar nicht erst angestoßen. Daraus folgt insbesondere, dass +in diesem Fall nur die in der BeanInfo-Klasse angegebenen Merkmale +zur Verfügung stehen. + +

+Ist es beispielsweise nötig, eine BeanInfo-Klasse zur Verfügung +zu stellen, weil dem Designer eine besondere Methode bekanntgemacht +werden soll, die nicht den getter-/setter-Konventionen entspricht, +muss die BeanInfo-Klasse auch alle anderen Eigenschaften der Bean +explizit bekanntmachen. Andernfalls würde der GUI-Designer nur +die spezielle Methode sehen, alle anderen Merkmale aber ignorieren.

+ + + + +
 Warnung 
+
+ + + + +

getIcon

+

+ + + + + +
+ +
+public Image getIcon(int iconKind)
+
+
+
+java.beans.BeanInfo
+ +

+Der GUI-Designer ruft getIcon +auf, um herauszufinden, ob die Bean ein Icon zur Darstellung in der +Toolbox zur Verfügung stellen kann. Als Parameter wird dabei +eine der symbolischen Konstanten ICON_COLOR_16x16, +ICON_MONO_16x16, +ICON_COLOR_32x32 +oder ICON_MONO_32x32 +übergeben. Kann die BeanInfo-Klasse ein Icon in der gewünschten +Form zur Verfügung stellen, muss sie ein passendes Image-Objekt +erzeugen und an den Aufrufer zurückgeben. Ist das nicht der Fall, +sollte null +zurückgegeben werden. +

+ + + + + + + + + + + +
+ +

+Ist die BeanInfo-Klasse aus SimpleBeanInfo +abgeleitet, ist das Erzeugen eines Image-Objekts +einfach. SimpleBeanInfo +besitzt eine Methode loadImage, +die bei Übergabe eines Dateinamens die ensprechende Bilddatei +lädt und daraus ein Image +erzeugt.

+ + + + +
 Tipp 
+
+ + + + +

getPropertyDescriptors

+

+ + + + + +
+ +
+public PropertyDescriptor[] getPropertyDescriptors()
+
+
+
+java.beans.BeanInfo
+ +

+Die Methode getPropertyDescriptors +wird aufgerufen, um ein Array von PropertyDescriptor-Objekten +zur Verfügung zu stellen. Es enthält für jede öffentliche +Eigenschaft der Bean ein Element, das dessen Merkmale beschreibt. +Ein PropertyDescriptor +kann recht einfach instanziert werden: +

+ + + + + +
+ +
+public PropertyDescriptor(String propertyName, Class beanClass)
+  throws IntrospectionException
+
+
+
+java.beans.PropertyDescriptor
+ +

+Lediglich der Name der Eigenschaft und das Klassenobjekt der zugehörigen +Bean sind anzugeben. Weitere Merkmale können durch Methodenaufrufe +hinzugefügt werden. Uns interessiert an dieser Stelle lediglich +die Methode setPropertyEditorClass, +auf die wir in Abschnitt 44.6.2 +zurückkommen werden. +

+ + + + + + + + + +
+ +

+Für jedes von getPropertyDescriptors +zurückgegebene Element erwartet der GUI-Designer eine setter- +und eine getter-Methode, deren Signatur dem bekannten Schema entsprechen +muss.

+ + + + +
 Hinweis 
+
+ + + + +

getMethodDescriptors

+

+ + + + + +
+ +
+public MethodDescriptor[] getMethodDescriptors()
+
+
+
+java.beans.BeanInfo
+ +

+Zusätzliche Methoden können dem GUI-Designer durch Überlagern +von getMethodDescriptors +bekanntgemacht werden. Zurückgegeben wird ein Array, das für +jede Methode ein Objekt des Typs MethodDescriptor +enthält. Darin wird im wesentlichen ein Method-Objekt +gekapselt (siehe Abschnitt 43.3): +

+ + + + + +
+ +
+public MethodDescriptor(Method method)
+
+
+
+java.beans.MethodDescriptor
+ + + + +

Die Klasse LightBulbBeanInfo

+ +

+Nach diesen Vorbemerkungen können wir eine geeignete BeanInfo-Klasse +für die LightBulb-Komponente +entwickeln: + + +

+ + + + + +
+ +
+001 /* LightBulbBeanInfo.java */
+002 
+003 import java.awt.*;
+004 import java.beans.*;
+005 import java.lang.reflect.*;
+006 
+007 public class LightBulbBeanInfo
+008 extends SimpleBeanInfo
+009 {
+010   public Image getIcon(int iconKind)
+011   {
+012     String imgname = "bulbico16.gif";
+013     if (iconKind == BeanInfo.ICON_MONO_32x32 ||
+014         iconKind == BeanInfo.ICON_COLOR_32x32) {
+015       imgname = "bulbico32.gif";
+016     }
+017     return loadImage(imgname);
+018   }
+019 
+020   public PropertyDescriptor[] getPropertyDescriptors()
+021   {
+022     try {
+023       PropertyDescriptor pd1 = new PropertyDescriptor(
+024         "lightOn",
+025         LightBulb.class
+026       );
+027       //pd1.setPropertyEditorClass(LightBulbLightOnEditor1.class); 
+028       PropertyDescriptor[] ret = {pd1};
+029       return ret;
+030     } catch (IntrospectionException e) {
+031       System.err.println(e.toString());
+032       return null;
+033     }
+034   }
+035 
+036   public MethodDescriptor[] getMethodDescriptors()
+037   {
+038     MethodDescriptor[] ret = null;
+039     try {
+040       Class bulbclass = LightBulb.class;
+041       Method meth1 = bulbclass.getMethod("toggleLight", null);
+042       ret = new MethodDescriptor[1];
+043       ret[0] = new MethodDescriptor(meth1);
+044     } catch (NoSuchMethodException e) {
+045       //ret bleibt null
+046     }
+047     return ret;
+048   }
+049 }
+
+
+LightBulbBeanInfo.java
+ +Listing 44.10: Die Klasse LightBulbBeanInfo

+ +

+Wird die Klasse übersetzt und in die jar-Datei für die Beanbox +aufgenommen, verändert sich die Präsentation der LighBulb-Bean +in der Beanbox: +

+ +

+Während die ersten beiden Veränderungen nach dem Starten +der Beanbox offensichtlich sind, können wir die letzte überprüfen, +indem wir den Aufruf von toggleLight +auf das Ereignis einer anderen Bean legen. Dazu platzieren wir im +GUI-Designer zunächst eine LightBulb- +und eine LightedPushButton-Bean. +Anschließend markieren wir die LightedPushButton-Bean +und rufen den Menüpunkt »Edit.Events.PropertyChange.propertyChange« +auf. Die rote Verbindungslinie ziehen wir auf die LightBulb +und fixieren sie dort mit einem Mausklick. + +

+Aus der Auswahlliste der verfügbaren parameterlosen Methoden +können wir nun toggleLight +auswählen und »OK« drücken. Die Beanbox generiert +und übersetzt nun eine Adapterklasse, die bei jedem PropertyChangeEvent +des LightedPushButton die Methode +toggleLight der LightBulb +aufruft. Nach jedem Drücken des Buttons verändert die Lampe +also ihren Zustand. Die Lampe kann natürlich nach wie vor auch +im Eigenschaftenfenster an- und ausgeschaltet werden. + + + + +

44.6.2 Property-Editoren

+ +

+Die Beanbox und andere GUI-Designer stellen für einfache Eigenschaften +vordefinierte Editoren zur Verfügung, mit denen ihr Wert verändert +werden kann. Bereits bei indizierten Eigenschaften muss die Beanbox +aber passen. Auch für Objekttypen kann ein GUI-Designer keinen +Standard-Editor zur Verfügung stellen, weil er die Konfigurationsschnittstelle +des Objekts nicht kennt. Für diesen Zweck bietet die Beans-Architektur +die Möglichkeit, eigene Editoren zu definieren und bestimmten +Eigenschaften von Beans zuzuordnen. + +

+In Zeile 027 von Listing 44.10 +ist der Aufruf von setPropertyEditorClass +auskommentiert, damit die Beanbox den eingebauten Editor für +boolesche Werte verwendet. Durch Entfernen des Kommentars erhält +der PropertyDescriptor +der Eigenschaft »lightOn« die Information, dass zum Editieren +dieser Eigenschaft ein benutzerdefinierter Editor verwendet werden +soll. + +

+Benutzerdefinierte Eigenschafteneditoren werden üblicherweise +aus der Klasse PropertyEditorSupport +des Pakets java.beans +abgeleitet. Sie besitzt eine Reihe von Methoden, die in eigenen Editoren +überlagert werden: +

+ + + + + +
+ +
+public void setValue(Object value)
+public Object getValue()
+
+public String getAsText()
+
+public void setAsText(String text)
+  throws java.lang.IllegalArgumentException
+
+public String[] getTags()
+
+public boolean isPaintable()
+
+public boolean supportsCustomEditor()
+
+public void paintValue(Graphics g, Rectangle box)
+
+public Component getCustomEditor()
+
+
+
+java.beans.PropertyEditorSupport
+ +

+In den nächsten Abschnitten werden wir drei Editoren für +die Eigenschaft »lightOn« vorstellen. Sie machen in unterschiedlicher +Weise von diesen Methoden Gebrauch. +

+ + + + + + + + + +
+ +

+Eine weitere Variante zur Konfiguration von Beans (auf die wir hier +nicht näher eingehen wollen) ist die Implementierung eines Customizers. +Dieser erhält volle Kontrolle über die Konfiguration der +Bean. Er kann insbesondere auch mehrere Eigenschaften gleichzeitig +verändern und auf diese Weise aufwändige Editoren zur Verfügung +stellen, die den bekannten Wizards oder Assistenten +moderner Entwicklungssysteme ähneln.

+ + + + +
 Hinweis 
+
+ + + + +

LightBulbLightOnEditor1

+ +

+Der erste Editor ist sehr einfach aufgebaut. Er stellt ein Textfeld +zur Verfügung, in dem die Werte »an« und »aus« +eingegeben werden können, um den Zustand der Lampe umzuschalten. + +

+Jeder der nachfolgend vorgestellten Editoren kapselt eine boolesche +Membervariable currentvalue, +die den aktuellen Zustand der Lampe festhält. Sie wird vom GUI-Designer +durch Aufruf von getValue +abgefragt und durch setValue +gesetzt. Beide Methoden operieren mit Objekttypen, d.h. es ist jeweils +eine Konvertierung zwischen boolean +und Boolean +erforderlich. In unserem Beispiel werden zusätzlich die Methoden +getAsText +und setAsText +überlagert, um auf die textuelle Repräsentation (»an« +und »aus«) des booleschen Werts zuzugreifen. + + +

+ + + + + +
+ +
+001 /* LightBulbLightOnEditor1.java */
+002 
+003 import java.awt.*;
+004 import java.beans.*;
+005 
+006 public class LightBulbLightOnEditor1
+007 extends PropertyEditorSupport
+008 {
+009   boolean currentvalue;
+010 
+011   public void setValue(Object value)
+012   {
+013     currentvalue = ((Boolean)value).booleanValue();
+014   }
+015 
+016   public Object getValue()
+017   {
+018     return new Boolean(currentvalue);
+019   }
+020 
+021   public String getAsText()
+022   {
+023     return "" + (currentvalue ? "an" : "aus");
+024   }
+025 
+026   public void setAsText(String text)
+027   throws java.lang.IllegalArgumentException
+028   {
+029     if (text.equalsIgnoreCase("an")) {
+030       currentvalue = true;
+031     } else if (text.equalsIgnoreCase("aus")) {
+032       currentvalue = false;
+033     } else {
+034       throw new IllegalArgumentException(text);
+035     }
+036     firePropertyChange();
+037   }
+038 }
+
+
+LightBulbLightOnEditor1.java
+ +Listing 44.11: Die Klasse LightBulbLightOnEditor1

+ +

+Der erste Editor sieht in der Beanbox so aus: +

+ + +

+ +

+Abbildung 44.8: LightBulbLightOnEditor1 in der Beanbox

+ + + + +

LightBulbLightOnEditor2

+ +

+Ist der Wertevorrat für die zu editierende Eigenschaft endlich, +kann es bequemer sein, dem Anwender alle möglichen Varianten +in einer Combox anzubieten. Dazu muss lediglich die Methode getTags +überlagert und ein Array von Strings mit den möglichen Werten +zurückgegeben werden: + + +

+ + + + + +
+ +
+001 /* LightBulbLightOnEditor2.java */
+002 
+003 import java.awt.*;
+004 import java.beans.*;
+005 
+006 public class LightBulbLightOnEditor2
+007 extends PropertyEditorSupport
+008 {
+009   boolean currentvalue;
+010 
+011   public void setValue(Object value)
+012   {
+013     currentvalue = ((Boolean)value).booleanValue();
+014   }
+015 
+016   public Object getValue()
+017   {
+018     return new Boolean(currentvalue);
+019   }
+020 
+021   public String getAsText()
+022   {
+023     return "" + (currentvalue ? "an" : "aus");
+024   }
+025 
+026   public void setAsText(String text)
+027   throws java.lang.IllegalArgumentException
+028   {
+029     System.out.println("setAsText(" + text + ")");
+030     if (text.equalsIgnoreCase("an")) {
+031       currentvalue = true;
+032     } else if (text.equalsIgnoreCase("aus")) {
+033       currentvalue = false;
+034     } else {
+035       throw new IllegalArgumentException(text);
+036     }
+037     firePropertyChange();
+038   }
+039 
+040   public String[] getTags()
+041   {
+042     return new String[]{"aus", "an"};
+043   }
+044 }
+
+
+LightBulbLightOnEditor2.java
+ +Listing 44.12: Die Klasse LightBulbLightOnEditor2

+ +

+Der zweite Editor sieht in der Beanbox so aus: +

+ + +

+ +

+Abbildung 44.9: LightBulbLightOnEditor2 in der Beanbox

+ + + + +

LightBulbLightOnEditor3

+ +

+Zusätzlich zu den beiden einfachen Varianten kann die Bean aber +auch einen vollkommen frei definierten Editor zur Verfügung stellen. +Sie ist in diesem Fall sowohl für die Darstellung der Eigenschaft +in der Eigenschaftenliste als auch für das Verändern des +aktuellen Wertes mit Hilfe einer eigenen Komponente verantwortlich. +Dazu werden weitere Methoden überlagert: +

+ +

+Die folgende Klasse LightBulbLightOnEditor3 +stellt einen sehr einfachen Editor zur Verfügung. Er besteht +lediglich aus zwei nebeneinanderliegenden Rechtecken in den Farben +Blau und Gelb. Die blaue Farbe symbolisiert den ausgeschalteten Zustand, +die gelbe den eingeschalteten. Der aktuelle Zustand der Lampe wird +durch einen schwarzen Rahmen um eines der beiden Rechtecke angezeigt. +Durch einfaches Anklicken eines der beiden Farbfelder kann der Zustand +umgeschaltet werden. + + +

+ + + + + +
+ +
+001 /* LightBulbLightOnEditor3.java */
+002 
+003 import java.awt.*;
+004 import java.awt.event.*;
+005 import java.beans.*;
+006 
+007 public class LightBulbLightOnEditor3
+008 extends PropertyEditorSupport
+009 {
+010   boolean currentvalue;
+011 
+012   public void setValue(Object value)
+013   {
+014     currentvalue = ((Boolean)value).booleanValue();
+015   }
+016 
+017   public Object getValue()
+018   {
+019     return new Boolean(currentvalue);
+020   }
+021 
+022   public boolean isPaintable()
+023   {
+024     return true;
+025   }
+026 
+027   public boolean supportsCustomEditor()
+028   {
+029     return true;
+030   }
+031 
+032   public Component getCustomEditor()
+033   {
+034     return new LightOnCustomEditor();
+035   }
+036 
+037   public void paintValue(Graphics g, Rectangle box)
+038   {
+039     //Linke Box: blau, Lampe ausgeschaltet
+040     g.setColor(Color.blue);
+041     g.fillRect(box.x, box.y, box.width / 2, box.height);
+042     //Rechte Box: blau, Lampe angeschaltet
+043     g.setColor(Color.yellow);
+044     g.fillRect(box.x + box.width / 2, box.y, box.width / 2, box.height);
+045     //Rahmen
+046     g.setColor(Color.black);
+047     for (int i = 0; i < 2; ++i) {
+048       g.drawRect(
+049         box.x + (currentvalue ? box.width / 2 : 0) + i,
+050         box.y + i,
+051         box.width / 2 - 1 - (2 * i),
+052         box.height - 1 - (2 * i)
+053       );
+054     }
+055   }
+056 
+057   //---Private Klassen----------------------------------------
+058   class LightOnCustomEditor
+059   extends Canvas
+060   {
+061     public LightOnCustomEditor()
+062     {
+063       addMouseListener(
+064         new MouseAdapter() {
+065           public void mouseClicked(MouseEvent event)
+066             {
+067               currentvalue = (event.getX() > getSize().width / 2);
+068               LightBulbLightOnEditor3.this.firePropertyChange();
+069               repaint();
+070             }
+071           }
+072         );
+073     }
+074 
+075     public void paint(Graphics g)
+076     {
+077       paintValue(g, new Rectangle(0, 0, getSize().width, getSize().height));
+078     }
+079 
+080     public Dimension getPreferredSize()
+081     {
+082       return new Dimension(120, 60);
+083     }
+084   }
+085 }
+
+
+LightBulbLightOnEditor3.java
+ +Listing 44.13: Die Klasse LightBulbLightOnEditor3

+ +

+Der Editor wird durch die aus Canvas +abgeleitete lokale Klasse LightOnCustomEditor +implementiert. Ihre bevorzugte Größe ist fest eingestellt, +und sie verwendet die paintValue-Methode +der umgebenden Klasse zur Bildschirmdarstellung. Bei einem Mausklick +verändert sie deren Membervariable currentvalue +und teilt dies dem GUI-Designer durch Aufruf von firePropertyChange +mit. Anschließend ruft sie repaint +auf, um den Rahmen neu zu zeichnen. + +

+Der dritte Editor sieht in der Eigenschaftenliste so aus: +

+ + +

+ +

+Abbildung 44.10: LightBulbLightOnEditor3 in der Beanbox

+ +

+Wird er angeklickt, erzeugt die Beanbox eine vergrößerte +Variante, in der der Wert verändert werden kann: +

+ + +

+ +

+Abbildung 44.11: LightBulbLightOnEditor3 in der Eigenschaftenliste

+
+ + + +
 Titel  + Inhalt  + Suchen  + Index  + DOC  +Handbuch der Java-Programmierung, 5. Auflage, Addison +Wesley, Version 5.0.1 +
 <<  +  <   +  >   + >>  + API  +© 1998, 2007 Guido Krüger & Thomas +Stark, http://www.javabuch.de +
+ + + -- cgit v1.2.3