Erstellen einer einfachen JavaBean
|
proj006c_EventTest_Schieber.zip - Musterlösung zur Übung.
Eine Java-Bean muß die Schnittstelle "Serializable" implementieren, damit aktuelle Einstellungen der Attribute eines Objektes der Klasse auf einfache Weise dauerhaft gespeichert werden können. Es macht Sinn ein Java-Bean von einem GUI-Element abzuleiten, damit es später über die Entwicklungsumgebung mit Drag and Drop in eine Oberfläche eingebaut werden kann.
Als Beispiel wird in mehreren Schritte ein Textfenster als Java-Bean entwickelt. Bevor es als Java-Bean in der Entwicklungsumgebung verwendet wird, wird es auch durch ein einfaches Testprogramm überprüft. Das Projekt findet sich im Ordner proj006a_Parameterfeld und besteht aus den Quelltextdateien ParametereingabeBean.java (dies wird die Java-Bean) und TestParametereingabeBean.java (erzeugt eine einfache Oberfläche zum Testen von ParametereingabeBean).
Projekt proj006a_Parameterfeld
import java.awt.Color; import java.beans.XMLDecoder; import java.awt.*; import javax.swing.*; import java.io.Serializable; public class ParametereingabeBean extends JPanel implements Serializable { private JLabel aufkleber; private JTextField textfeld; /** Für die einzustellenden Parameter müssen get- und set-Methoden bereitgestellt werden. */ private double wert; private String bezeichnung; /** JavaBeans müssen einen leeren Kontruktor besitzen. */ public ParametereingabeBean() { wert = 0.0; bezeichnung = "Zahl"; textfeld = new JTextField(""+wert); aufkleber = new JLabel(bezeichnung); setLayout(new GridLayout(1,2)); setBounds(10,60,300,30); add(aufkleber); add(textfeld); setBackground( Color.BLUE ); aufkleber.setForeground( Color.WHITE ); } }
Code 0-1: Projekt proj006a_Parameterfeld, Java-Klasse ParametereingabeBean (Java-Bean) in der Datei ParametereingabeBean.java
Bild 0-1: Erster Test für ein Element zur Parametereingabe (javac *.java, anschließend: Java TestParametereingabeBean).
|
|
import java.applet.*; import java.awt.*; import javax.swing.*; import java.io.*; public class TestParametereingabeBean { public static void main(String[] args) { JFrame mF = new JFrame("TestParametereingabeBean"); mF.setLayout(null); mF.getContentPane().add(new ParametereingabeBean()); mF.pack(); mF.setSize(500,500); mF.setLocation(10,10); mF.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mF.setVisible(true); } }
Code 0-2: Projekt proj006a_Parameterfeld, Java-Klasse TestParametereingabeBean in der Datei TestParametereingabeBean.java
proj006b_GetterSetter
Damit den für Java-Beans bestehenden Konventionen Genüge getan wird, muß für jedes Attribut, für das die Entwicklungsumgebung automatisch ein Parametereingabefeld erzeugen soll eine get- und eine set-Methode geschrieben werden:
public class ParametereingabeBean extends JPanel implements Serializable { private JLabel aufkleber; private JTextField textfeld; /** Für die einzustellenden Parameter müssen get- und set-Methoden bereitgestellt werden. */ private double wert; private String bezeichnung; private int breite; private int hoehe; public void setWert(double wert) { textfeld.setText(""+wert); this.wert=wert; } public double getWert() { try { double x = Double.parseDouble(textfeld.getText()); this.wert = x; } catch(Exception e) { } return this.wert; } public void setBezeichnung(String bezeichnung) { aufkleber.setText(bezeichnung); this.bezeichnung=bezeichnung; } public String getBezeichnung() { return this.bezeichnung; } public void setBreite(int breite) { Dimension dim = this.getSize(); this.setSize(breite,(int)dim.getHeight()); this.breite = breite; } public int getBreite() { return this.breite; } public void setHoehe(int hoehe) { Dimension dim = this.getSize(); this.setSize((int)dim.getWidth(),hoehe); this.hoehe = hoehe; } public int getHoehe() { return this.hoehe; } /** JavaBeans müssen einen leeren Kontruktor besitzen. */ public ParametereingabeBean() { wert = 0.0; bezeichnung = "Zahl"; textfeld = new JTextField(""+wert); aufkleber = new JLabel(bezeichnung); setLayout(new GridLayout(1,2)); breite = 300; hoehe = 30; setBounds(10,60,breite,hoehe); add(aufkleber); add(textfeld); setBackground( Color.BLUE ); aufkleber.setForeground( Color.WHITE ); } }
Code 0-3: proj006b_GetterSetter, Java-Klasse ParametereingabeBean (Java-Bean) in der Datei ParametereingabeBean.java
Um die Einstellmöglichkeiten zu testen, wird auch die Testklasse erweitert:
import java.applet.*; import java.awt.*; import javax.swing.*; import java.io.*; public class TestParametereingabeBean { public static void main(String[] args) { JFrame mF = new JFrame("TestParametereingabeBean"); mF.setLayout(null); ParametereingabeBean meineParametereingabeBean = new ParametereingabeBean(); mF.getContentPane().add(meineParametereingabeBean); mF.pack(); mF.setSize(500,500); mF.setLocation(10,10); mF.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mF.setVisible(true); meineParametereingabeBean.setWert(3.5); meineParametereingabeBean.setBezeichnung("Wert:"); meineParametereingabeBean.setBreite(500); meineParametereingabeBean.setHoehe(50); System.out.println("Aktuelle Bezeichnung: "+meineParametereingabeBean.getBezeichnung()); System.out.println("Aktueller Wert: "+meineParametereingabeBean.getWert()); } }
Code 0-4: proj006b_GetterSetter, Java-Klasse TestParametereingabeBean in der Datei TestParametereingabeBean.java
Bild 0-2: Ergenis der Änderungen der Objekteigenschaften über die set-Methoden.
proj006c_EventTest
Nun sollen drei Parameter-Eingabe-Objekte erstellt werden und im dritten immer die Summe der ersten beiden erscheinen.
Bild 0-3: Programm, um die Summe zweier Anzeigefelder zu bilden.
Bei der Realisierung müssen folgende Probleme gelöst werden:
|
Dabei ist firePropertyChange("wert",wert_alt,wert) eine spezielle Bean-Methode, die sowieso für die Kommunikation von Beans untereinander bestimmt ist.
|
Es folgen die Quelltexte:
import java.awt.Color; import java.beans.XMLDecoder; import java.awt.*; import javax.swing.*; import java.io.Serializable; public class ParametereingabeBean extends JPanel implements Serializable { private JLabel aufkleber; private Textfeld textfeld; /** Für die einzustellenden Parameter müssen get- und set-Methoden bereitgestellt werden. */ private double wert; private String bezeichnung; private int breite; private int hoehe; public void setWert(double wert) { textfeld.setText(""+wert); this.wert=wert; } public double getWert() { try { double x = Double.parseDouble(textfeld.getText()); this.wert = x; } catch(Exception e) { } return this.wert; } public void setBezeichnung(String bezeichnung) { aufkleber.setText(bezeichnung); this.bezeichnung=bezeichnung; } public String getBezeichnung() { return this.bezeichnung; } public void setBreite(int breite) { Dimension dim = this.getSize(); this.setSize(breite,(int)dim.getHeight()); this.breite = breite; } public int getBreite() { return this.breite; } public void setHoehe(int hoehe) { Dimension dim = this.getSize(); this.setSize((int)dim.getWidth(),hoehe); this.hoehe = hoehe; } public int getHoehe() { return this.hoehe; } public void setWertIntern(String text) { double x = wert; double wert_alt = wert; boolean ok = true; try { x = Double.parseDouble(text); } catch(Exception e) { ok = false; } if( ok==true ) wert = x; firePropertyChange("wert",wert_alt,wert); } /** JavaBeans müssen einen leeren Kontruktor besitzen. */ public ParametereingabeBean() { wert = 0.0; bezeichnung = "Zahl"; textfeld = new Textfeld(this,""+wert); aufkleber = new JLabel(bezeichnung); setLayout(new GridLayout(1,2)); breite = 300; hoehe = 30; setBounds(10,60,breite,hoehe); add(aufkleber); add(textfeld); setBackground( Color.BLUE ); aufkleber.setForeground( Color.WHITE ); } }
Code 0-5: proj006c_EventTest, Java-Klasse ParametereingabeBean (Java-Bean) in der Datei ParametereingabeBean.java
import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.beans.*; public class EreignisseVerarbeiten implements PropertyChangeListener { private ParametereingabeBean pb1; private ParametereingabeBean pb2; private ParametereingabeBean pb3; EreignisseVerarbeiten(ParametereingabeBean pb1, ParametereingabeBean pb2, ParametereingabeBean pb3) { this.pb1 = pb1; this.pb2 = pb2; this.pb3 = pb3; } public void propertyChange(PropertyChangeEvent evt) { System.out.println("Text geändert"); pb3.setWert(pb1.getWert()+pb2.getWert()); } }
Code 0-6: proj006c_EventTest, Java-Klasse EreignisseVerarbeiten in der Datei EreignisseVerarbeiten.java
|
import javax.swing.*; import java.awt.event.*; import java.awt.*; import java.beans.*; public class Textfeld extends TextField { private ParametereingabeBean pb; public void aktivieren() { enableEvents (AWTEvent.ACTION_EVENT_MASK); enableEvents (AWTEvent.TEXT_EVENT_MASK); enableEvents (AWTEvent.FOCUS_EVENT_MASK); } Textfeld(ParametereingabeBean pb,String text) { super(text); aktivieren(); this.pb = pb; } protected void processEvent(AWTEvent e) { pb.setWertIntern(getText()); } }
Code 0-7: proj006c_EventTest, Java-Klasse Textfeld in der Datei Textfeld.java
An der main-Methode im Quelltext TestParametereingabeBean.java ist zu ersehen, wie die Objekte miteinander verschaltet werden: Alle drei Eingabefelder meineParametereingabeBean1..3 werden in ev registriert. Dies erfolgt durch Übergabe an den Konstruktor und darin durch Speichern der übergebenen Referenzen als Attribute. Als zweites wird der Listener ev (vom Typ EreignisseVerarbeiten) bei allen drei ParametereingabeBean-Objekten über addPropertyChangeListener(ev) registriert. Dadurch reagiert dann die Methode propertyChange(PropertyChangeEvent evt) in ev auf jede Textänderung in jedem Parameter-Eingabe-Objekt.
import java.applet.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.io.*; import java.beans.*; public class TestParametereingabeBean { public static void main(String[] args) { JFrame mF = new JFrame("TestParametereingabeBean"); mF.setLayout(new GridLayout(3,1)); ParametereingabeBean meineParametereingabeBean1 = new ParametereingabeBean(); ParametereingabeBean meineParametereingabeBean2 = new ParametereingabeBean(); ParametereingabeBean meineParametereingabeBean3 = new ParametereingabeBean(); mF.getContentPane().add(meineParametereingabeBean1); mF.getContentPane().add(meineParametereingabeBean2); mF.getContentPane().add(meineParametereingabeBean3); mF.pack(); mF.setSize(500,100); mF.setLocation(10,10); mF.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mF.setVisible(true); EreignisseVerarbeiten ev = new EreignisseVerarbeiten(meineParametereingabeBean1, meineParametereingabeBean2, meineParametereingabeBean3); meineParametereingabeBean1.addPropertyChangeListener(ev); meineParametereingabeBean2.addPropertyChangeListener(ev); meineParametereingabeBean3.addPropertyChangeListener(ev); meineParametereingabeBean1.setWert(1.0); meineParametereingabeBean1.setBezeichnung("Wert1:"); meineParametereingabeBean2.setWert(2.0); meineParametereingabeBean2.setBezeichnung("Wert2:"); meineParametereingabeBean3.setWert(3.0); meineParametereingabeBean3.setBezeichnung("Wert1+Wert2:"); } }
Code 0-8: proj006c_EventTest, Java-Klasse TestParametereingabeBean in der Datei TestParametereingabeBean.java
Das Projekt proj006d_InnereKlasse entspricht weitestgehend proj006c_EventTest. Allerdings wurde hier die Klasse Textfeld als innere Klasse von ParametereingabeBean umgesetzt. Dies ermöglicht dem Textfeld-Objekt den direkten Zugriff auf die Methode setWertIntern(...) des übergeordneten Objektes vom Typ ParametereingabeBean, ohne dass dieses extra beim Textfeld-Objekt registriert werden müßte. /p>
Bisher wurde eine Testanwendung für ParametereingabeBean umgesetzt. Zukünftig soll ParametereingabeBean als Drag and Drop-Element in der Entwicklungsumgebung NetBeansIDE eingebunden werden. Vorbereitend darauf muß die Klasse ParametereingabeBean in eine gepackte Datei vom Typ .jar umgewandelt werden. Dies geht am einfachsten mit der Skriptsprache ANT unter Verwendung eines XML-Skriptes mit dem Namen build.xml. Die Umwandlung erfolgt, wenn ParametereingabeBean.java und build.xml im gleichen Verzeichnis liegen und dort einfach "ant" von der Konsole aus aufgerufen wird. Sowohl das Kompilieren, als auch die Erstellung der .jar-Datei wird dann von ANT übernommen. Andere Klassen können leicht genauso behandelt werden. Lediglich der Eintrag des Klassennamens in der build.xml-Datei muß hierfür angepaßt werden. Im folgenden ist der Inhalt von build.xml zu sehen: /p>
<?xml version="1.0" encoding="ISO-8859-1"?> <project default="build"> <dirname property="basedir" file=""/> <property name="beanname" value="ParametereingabeBean"/> <property name="jarfile" value="/.jar"/> <target name="build" depends="compile"> <jar destfile="" basedir="" includes="*.class"> <manifest> <section name=".class"> <attribute name="Java-Bean" value="true"/> </section> </manifest> </jar> </target> <target name="compile"> <javac destdir=""> <src location=""/> </javac> </target> <target name="clean"> <delete file=""> <fileset dir="" includes="*.class"/> </delete> </target> </project>
Code 0-9: proj006e_JavaBean, build.xml
Übung
|