7.9.4 Beispiel: Fenster mit Label und Buttons

Das folgende Beispiel ist die internationalisierte und parametrisierte Version des Beispiels von Kap.7.5.4

Zu den Klassen:
LabelButtonFensterKonstante
LabelButtonFensterV
Zu den Ressource- und Properties-Dateien:
Ressource-Dateien
Properties-Datei

7.9.4.1 Statische Klasse für Ressource- und Properties-Konstante

Klasse LabelButtonFensterKonstante
/* * LabelButtonFensterKonstante.java */ package at.beringer.oopBuch.guiSwingI18N; import java.util.Locale; import java.util.ResourceBundle; import java.util.Properties; import java.io.FileInputStream; import java.io.IOException; /** Statische Klasse für Ressource- und Properties-Konstante. <p> Texte und Beschriftungen werden aus einer (lokalisierten) Ressource-Datei gelesen. <br /> Die Dateinamenserweiterung von Ressource-Dateien muss 'properties' sein. </p> <p> Bem.: Klassen-Dateien und Bild-Dateien sind ebenfalls Ressourcen. </p> <p> Ressource-Dateien müssen INNERHALB des Klassenpfads liegen. </p> <p> Verzeichnis für die Ressource-Dateien: <br /> <pre> <strong>at.beringer.oopBuch.resources</strong> </pre> </p> <p> Basisname der Ressource-Dateien: <br /> <pre> <strong>labelButtonFenster</strong> </pre> </p> <p> --> vollständiger qualifizierter Name der Ressource-Dateien: <br /> <pre> at.beringer.oopBuch.resources.labelButtonFenster.properties at.beringer.oopBuch.resources.labelButtonFenster_de_AT.properties at.beringer.oopBuch.resources.labelButtonFenster_en.properties </pre> <br /> usw. </p> <p> Die JVM sucht - analog zur Suche einer Klasse - automatisch nach der entsprechenden (lokalisierten) Ressource-Datei. <br /> Die JVM behandelt eine Ressource-Datei wie eine Klasse, u.a. wird eine Resource-Datei automatisch geladen. Wenn die Datei nicht existiert, wird eine 'MissingResourceException' ausgelöst. </p> <p> Der Benutzer kann (und darf) Ressource-Dateien <strong>nicht</strong> ändern. </p><hr /><p> Nichtlokalisierte Konstante können in Properties-Dateien definiert werden. Im Allg. ist die Dateinamenserweiterung von Properties-Dateien 'properties', allerdings ist - im Gegensatz zu Ressource-Dateien - jede beliebige Dateinamenserweiterung erlaubt. </p> <p> Properties-Dateien müssen AUSSERHALB des Klassenpfads liegen. </p> <p> Name der Properties-Datei für nichtlokalisierte Konstante: <br /> <pre> <strong>labelButtonFenster.properties</strong> </pre> </p> <p> Diese Properties-Datei muss enthalten sein im Unterverzeichnis<br /> <pre> <strong>at/beringer/oopBuch/properties</strong> </pre> <br /> des Benutzerverzeichnisses (d.h. des Projektverzeichnis). </p> <p> --> vollständiger qualifizierter Name der Properties-Datei: <br /> <pre> <strong>at/beringer/oopBuch/properties/labelButtonFenster.properties </strong> </pre> </p> <dl> <dt>Bem.: <dd>Ressource- und Properties-Dateien befinden sich immer in unterschiedlichen Verzeichnissen (innerhalb bzw. außerhalb des Klassenpfads). Daher können die Dateinamen von Ressource- und Properties- Dateien gleich sein (müssen aber nicht). </dl> <p> Der Benutzer kann (und darf) Properties-Dateien ändern. </p> <hr /> @since Juli 2012 @see LabelButtonFensterV @author Beringer Alfred */ public final class LabelButtonFensterKonstante { // ------------------------------------------------------------------------- // Private Klassenkonstante // ------------------------------------------------------------------------- // ------------------------------------------------------------------------- // Ressource-Datei /** Basisname der Ressource-Dateien für lokalisierte Konstante (Texte und Beschriftungen) */ private static final String RESS_DATEINAME = "at.beringer.oopBuch.resources.labelButtonFenster"; /** Ressource-Datei für lokalisierte Konstante (Texte und Beschriftungen). <p> Die JVM sucht - analog zur Suche einer Klasse - automatisch nach der entsprechenden Ressource-Datei. </p> */ private static final ResourceBundle RESS; // ------------------------------------------------------------------------- // Projekt-Verzeichnis /** Name des Projekt-Verzeichnisses */ private static final String PROJEKTVERZEICHNISNAME = System.getProperty("user.dir") + System.getProperty("file.separator") + "at" + System.getProperty("file.separator") + "beringer" + System.getProperty("file.separator") + "oopBuch" + System.getProperty("file.separator"); // ------------------------------------------------------------------------- // Properties-Datei /** Name der Properties-Datei (für nichtlokalisierte Konstante) */ private static final String PROPS_DATEINAME = PROJEKTVERZEICHNISNAME + "properties" + System.getProperty("file.separator") + "labelButtonFenster.properties"; /** Properties-Datei für nichtlokalisierte Konstante */ private static final Properties PROPS; // ------------------------------------------------------------------------- // Öffentliche Klassenkonstante // ------------------------------------------------------------------------- // ------------------------------------------------------------------------- // System Konstante: public static final String NEUEZEILE = System.getProperty("line.separator"); // ------------------------------------------------------------------------- // Lokalisierte Konstante: // Texte und Beschriftungen für GUI-Komponenten: public static final String FENSTERTITEL; public static final String LABELTEXT; public static final String SCHALTFLAECHE1; public static final String SCHALTFLAECHE2; public static final String TOOLTIP1; public static final String TOOLTIP2; public static final char MNEMONIC1; public static final char MNEMONIC2; // ------------------------------------------------------------------------- // Nichtlokalisierte Konstante: // Fenstergröße (Hauptfenster) public static final int FENSTERBREITE; private static final String FENSTERBREITEstr; public static final int FENSTERHOEHE; private static final String FENSTERHOEHEstr; // Persönliche Daten des Autobesitzers (zum Initialisieren des Fachobjekts) public static final int BES_GEBURTSJAHR; public static final String BES_GEBURTSJAHRstr; public static final char BES_GESCHLECHT; public static final String BES_VORNAME; // ------------------------------------------------------------------------- // Klassenkonstruktor // ------------------------------------------------------------------------- /** Klassenkonstruktor. <br /> Initialisieren der Klassenkonstanten. <p> Die Anfangswerte für die Klassenkonstanten werden von einer Ressource- und einer Properties-Datei übernommen. </p> */ static { // --------------------------------------------------------------------- // Ressources RESS = ResourceBundle.getBundle(RESS_DATEINAME, Locale.getDefault()); FENSTERTITEL = RESS.getString("FENSTERTITEL"); LABELTEXT = RESS.getString("LABELTEXT"); SCHALTFLAECHE1 = RESS.getString("SCHALTFLAECHE1"); SCHALTFLAECHE2 = RESS.getString("SCHALTFLAECHE2"); TOOLTIP1 = RESS.getString("TOOLTIP1"); TOOLTIP2 = RESS.getString("TOOLTIP2"); MNEMONIC1 = RESS.getString("MNEMONIC1").charAt(0); MNEMONIC2 = RESS.getString("MNEMONIC2").charAt(0); // --------------------------------------------------------------------- // Properties PROPS = new Properties(); try { PROPS.load(new FileInputStream(PROPS_DATEINAME)); } catch (IOException exc) { System.err.println("Properties-Datei nicht gefunden!!!!!!!!"); // Default properties: PROPS.setProperty("FENSTERBREITE", "480"); PROPS.setProperty("FENSTERHOEHE", "260"); PROPS.setProperty("BES_GEBURTSJAHR", "1980"); PROPS.setProperty("BES_GESCHLECHT", "M"); PROPS.setProperty("BES_VORNAME", "Hugo"); } FENSTERBREITEstr = PROPS.getProperty("FENSTERBREITE"); FENSTERBREITE = Integer.parseInt(FENSTERBREITEstr); FENSTERHOEHEstr = PROPS.getProperty("FENSTERHOEHE"); FENSTERHOEHE = Integer.parseInt(FENSTERHOEHEstr); BES_GEBURTSJAHRstr = PROPS.getProperty("BES_GEBURTSJAHR"); BES_GEBURTSJAHR = Integer.parseInt(BES_GEBURTSJAHRstr); BES_GESCHLECHT = PROPS.getProperty("BES_GESCHLECHT").charAt(0); BES_VORNAME = PROPS.getProperty("BES_VORNAME"); } // ------------------------------------------------------------------------- // Konstruktoren // ------------------------------------------------------------------------- /** Privater Standardkonstruktor */ private LabelButtonFensterKonstante() { } }


7.9.4.2 Internationalisierte Klassendefinition des Fensters

Die folgende Klasse entspricht der Klasse aus dem Kap.7.5.4, wobei an Stelle eines einzigen Ereigniswächters jedem Ereignis ein eigener Ereigniswächter zugeordnet wurde. Für die Ereigniswächter wurden anonyme Klassen verwendet.

Klasse LabelButtonFensterV
/* * LabelButtonFensterV.java */ package at.beringer.oopBuch.guiSwingI18N; import javax.swing.*; import java.awt.*; import java.awt.event.*; import at.beringer.oopBuch.einfacheBsp.Auto; import at.beringer.oopBuch.einfacheBsp.Person; import static at.beringer.oopBuch.guiSwingI18N.LabelButtonFensterKonstante.*; /** Hauptfenster mit Text ('Label') und 2 Schaltfächen. <p> Anonyme Klasse: von 'ActionListener' <br /> Model-Klasse: 'Auto' (dient als Fachobjekt zum Testen dieser Fensterklasse) </p> <p> Diese Klasse ist die internationalisierte und parametrisierte Version der entsprechenden Klasse im Paket 'at.beringer.oopBuch.guiSwing'. <br /> Als frei wählbarer Parameter wurde die Fenstergröße gewählt. </p> <p> Alle Parameter - sowohl internationalisierte (wie Texte und Beschriftungen) wie auch nichtlokalisierte (wie die Fenstergröße) - wurden in die statische Klasse 'LabelButtonFensterKonstante' ausgelagert. </p> <p> Die lokalisierten Ressource-Dateien befinden sich im Paket 'at.beringer.oopBuch.resources'. <br /> Die lokalisierte Basisdatei heißt 'labelButtonFenster.properties'. <br /> Die Properties-Datei für die (nichtlokalisierten) Parameter befindet sich im Verzeichnis 'at/beringer/oopBuch/properties' und heißt ebenfalls 'labelButtonFenster.properties'. </p> <hr /> @since Juli 2012 @see LabelButtonFensterKonstante @see Auto @see Person @see ProgrammLabelButtonFenster @see at.beringer.oopBuch.guiSwing.LabelButtonFensterV @author Beringer Alfred */ public class LabelButtonFensterV extends JFrame { // ------------------------------------------------------------------------- // Instanzattribute // ------------------------------------------------------------------------- private JButton schaltflaeche1 = new JButton(SCHALTFLAECHE1); private JButton schaltflaeche2 = new JButton(SCHALTFLAECHE2); /** Model-Klasse: Fachobjekt (zum Testen) */ private Auto auto; // ------------------------------------------------------------------------- // Konstruktoren // ------------------------------------------------------------------------- /** Standardkonstruktor */ public LabelButtonFensterV() { this.setTitle(FENSTERTITEL); this.setSize(FENSTERBREITE, FENSTERHOEHE); this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // ToolTip (Quick-Help) schaltflaeche1.setToolTipText(TOOLTIP1); schaltflaeche2.setToolTipText(TOOLTIP2); // Tasten-Hotkey, wird unterstrichen angezeigt, // funktioniert nur mit ALT-Taste. schaltflaeche1.setMnemonic(MNEMONIC1); schaltflaeche2.setMnemonic(MNEMONIC2); // Layout des Fensters definieren und Komponenten dem Fenster hinzufügen this.setLayout(new FlowLayout()); this.add(new JLabel(LABELTEXT)); this.add(schaltflaeche1); this.add(schaltflaeche2); initListener(); initFachobjekt(); } // ------------------------------------------------------------------------- // Private Instanzmethoden // ------------------------------------------------------------------------- /** GUI-Komponenten bei Ereigniswächtern anmelden. <p> Alle Ereigniswächter werden durch anonyme Klassen definiert. </p> <p> Die Tätigkeiten in den überschriebenen API-Methoden werden in private Methoden ausgelagert, wobei die 'Event'-Objekte der API-Methoden an diese privaten Methoden immer weitergegeben werden, sodass Daten vom Ereignis zur Verfügung stehen, falls diese benötigt werden. </p> */ private void initListener() { schaltflaeche1.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent evt) { schaltflaeche1event(evt); } }); schaltflaeche2.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent evt) { schaltflaeche2event(evt); } }); } // ------------------------------------------------------------------------- /** Initialisieren des Fachobjekts. <p> Zum Testen wurden der Einfachheit halber willkürliche Werte in der Properties-Datei definiert. </p> */ private void initFachobjekt() { char geschlecht = BES_GESCHLECHT; /* Bem.: Die Klasse 'Person' ist nicht lokalisiert, daher sind die möglichen Kennzeichen für das Geschlecht immer fix vorgegeben. Das korrekte Kennzeichen muss also DIREKT in der Properties-Datei angegeben werden! Es ist aber möglich, auch dieses Kennzeichen zu internationalisieren. */ if ((geschlecht != Person.MAENNLICH) && (geschlecht != Person.WEIBLICH)) { geschlecht = Person.MAENNLICH; } auto = new Auto(); auto.setBesitzer(new Person(BES_GEBURTSJAHR, geschlecht)); auto.getBesitzer().aendernVorname(BES_VORNAME); } // ************************************************************************* // Ereignisbehandlungsmethoden // ************************************************************************* /** Methode für Schaltfläche1. @param evt ActionEvent (von API-Methode 'actionPerformed' übernommen) */ private void schaltflaeche1event(ActionEvent evt) { auto.raufschalten(); auto.zeigeInhalt(); } // ************************************************************************* /** Methode für Schaltfläche2. @param evt ActionEvent (von API-Methode 'actionPerformed' übernommen) */ private void schaltflaeche2event(ActionEvent evt) { auto.bremsen(); auto.zeigeInhalt(); } }


Bem.:
Die Klasse Person ist nicht lokalisiert, daher sind die möglichen Kennzeichen für das Geschlecht immer fix vorgegeben. Das korrekte Kennzeichen muss also DIREKT in der Properties-Datei angegeben werden!
Es ist aber möglich, auch dieses Kennzeichen zu internationalisieren.

7.9.4.3 Ressource-Dateien für lokalisierte Konstante

Basis-Ressource-Datei
at.beringer.oopBuch.resources.labelButtonFenster.properties
FENSTERTITEL = Swing-Fenster mit Label und Buttons (I18N) LABELTEXT = Auto\u0020\u0020 SCHALTFLAECHE1 = raufschalten SCHALTFLAECHE2 = \u0020\u0020bremsen\u0020\u0020 TOOLTIP1 = Gang um 1 erhöhen TOOLTIP2 = Geschwindigkeit um 10% vermindern MNEMONIC1 = R MNEMONIC2 = B


Ressource-Datei für englisch
at.beringer.oopBuch.resources.labelButtonFenster_en.properties
FENSTERTITEL = Swing window with Label and Buttons (I18N, en) LABELTEXT = Car\u0020\u0020 SCHALTFLAECHE1 = shift up SCHALTFLAECHE2 = \u0020\u0020brake\u0020\u0020 TOOLTIP1 = shift up gear by 1 TOOLTIP2 = reduce speed by 10% MNEMONIC1 = S MNEMONIC2 = B


Es können beliebig viele weitere lokalisierte Ressource-Dateien definiert werden.

7.9.4.4 Properties-Datei für nichtlokalisierte Konstante

Properties-Datei
at/beringer/oopBuch/properties/labelButtonFenster.properties
FENSTERBREITE = 400 FENSTERHOEHE = 260 # BES_GEBURTSJAHR = 1980 # Das Kennzeichen für das Geschlecht ist in der Klasse Person fix vorgegeben: BES_GESCHLECHT = M BES_VORNAME = Hugo



Weiter
zu den Java-GUI-Beispielen von Kapitel 7.10 (Dialogfenster)
zu Kapitel 8 (JDBC)
zu den C#-Klassenbeispielen von Kapitel 9.19.1 (Exceptions)
zu den C#-Klassenbeispielen von Kapitel 10 (Ein-/Ausgabe von Daten)
zu Kapitel 12 (PL/I)
zu Kapitel 13 (Reservierte Worte)
Zurück
zum Anfang dieses Kapitels
zum Inhaltsverzeichnis
 
zu Kapitel 1
zu den Klassenbeispielen von Kapitel 2
zur Parameterübergabe (Kapitel 2.7.1)
zu Kapitel 3
zu den Klassenbeispielen von Kapitel 4
zu den Java-Klassenbeispielen von Kapitel 5.19.1 (Exceptions)
zu den Java-Klassenbeispielen von Kapitel 6 (Ein-/Ausgabe von Daten)
zu den Java-GUI-Beispielen von Kapitel 7.4 (Einführung)
zu den Java-GUI-Beispielen von Kapitel 7.5 (Fenster mit Label und Buttons)
zu den Java-GUI-Beispielen von Kapitel 7.8 (Maus, Musterfenster, Menü)
Zur
Java-Dokumentation der Java-Beispiele