Skip to content

5. Grafische Benutzeroberflächen

Wir möchten hier zeigen, wie man mit JAVA grafische Benutzeroberflächen erstellt. Zunächst sehen wir uns an, welche Basisklassen uns die Erstellung einer grafischen Benutzeroberfläche ermöglichen. Zunächst verwenden wir kein Tool zur automatischen Generierung. Anschließend nutzen wir JBuilder, ein Entwicklungstool von Borland/Inprise, das die Entwicklung von Java-Anwendungen und insbesondere die Erstellung grafischer Benutzeroberflächen erleichtert.

5.1. Grundlagen grafischer Benutzeroberflächen

5.1.1. Ein einfaches Fenster

Betrachten wir den folgenden Code:


// importierte Klassen
import javax.swing.*;
import java.awt.*;
    
    // die Formularklasse
  public class form1 extends JFrame {
    
      // der Konstruktor
      public form1() {
            // Fenstertitel
            this.setTitle("Mon premier formulaire");
            // Fensterabmessungen
            this.setSize(new Dimension(300,100));
      }//Konstruktor
  
      // Testfunktion
      public static void main(String[] args) {
            // Das Formular wird angezeigt
            new form1().setVisible(true);
      }
  }//Klasse

Die Ausführung des obigen Codes zeigt das folgende Fenster an:

Image

Eine grafische Benutzeroberfläche leitet sich in der Regel von der Basisklasse JFrame ab:


  public class form1 extends JFrame {

Die Basisklasse JFrame definiert ein Basisfenster mit Schaltflächen zum Schließen, Vergrößern/Verkleinern, einer anpassbaren Größe usw. und verarbeitet die Ereignisse dieser grafischen Objekte. Hier spezialisieren wir die Basisklasse, indem wir ihr einen Titel sowie eine Breite (300 Pixel) und eine Höhe (100 Pixel) zuweisen. Dies geschieht in ihrem Konstruktor:


      // der Konstruktor
      public form1() {
            // Fenstertitel
            this.setTitle("Mon premier formulaire");
            // Fensterabmessungen
            this.setSize(new Dimension(300,100));
      }//Konstruktor

Der Titel des Fensters wird durch die Methode setTitle festgelegt, seine Abmessungen durch die Methode setSize. Diese Methode akzeptiert als Parameter ein Objekt vom Typ Dimension(largeur,hauteur), wobei largeur und hauteur die Breite und Höhe des Fensters in Pixeln angeben.

Die Methode main startet die Grafikanwendung wie folgt:


            new form1().setVisible(true);

Anschließend wird ein Formular vom Typ form1 erstellt (new form1()) und angezeigt (setVisible(true)), woraufhin die Anwendung auf Ereignisse wartet, die auf dem Formular auftreten (Klicks, Mausbewegungen, ...) und lässt diejenigen ausführen, die das Formular verarbeitet. In diesem Fall verarbeitet unser Formular keine anderen Ereignisse als diejenigen, die von der Basisklasse JFrame verarbeitet werden (Klicks auf Schaltflächen zum Schließen, Vergrößern/Verkleinern, Ändern der Fenstergröße, Verschieben des Fensters usw.).

Wenn man dieses Programm testet, indem man es über ein DOS-Fenster mit folgendem Befehl startet:

java form1

um die Datei form1.class auszuführen, stellt man fest, dass beim Schließen des angezeigten Fensters die Eingabe im DOS-Fenster nicht zurückgegeben wird, als ob das Programm noch nicht beendet wäre. Dies ist tatsächlich der Fall. Die Ausführung des Programms erfolgt wie folgt:

  • Zunächst wird ein erster Ausführungs-Thread gestartet, um die Methode main auszuführen
  • Wenn diese das Formular erstellt und anzeigt, wird ein zweiter Thread erstellt, um speziell die mit dem Formular verbundenen Ereignisse zu verarbeiten
  • Nach dieser Erstellung und in unserem Beispiel endet der Thread der Methode main, und es bleibt nur noch der Ausführungs-Thread der grafischen Benutzeroberfläche übrig.
  • Wenn man das Fenster schließt, verschwindet es, unterbricht jedoch nicht den Thread, in dem es ausgeführt wurde
  • Derzeit muss man diesen Thread zwangsläufig durch Drücken von Strg+C in dem DOS-Fenster beenden, von dem aus die Ausführung des Programms gestartet wurde.

Überprüfen wir das Vorhandensein von zwei getrennten Threads: einem, in dem die Methode main ausgeführt wird, und einem, in dem das grafische Fenster ausgeführt wird:


// importierte Klassen
import javax.swing.*;
import java.awt.*;
import java.io.*;

// die Formularklasse
 public class form1 extends JFrame {
    
// der Konstruktor
 public form1() {
   // Fenstertitel
   this.setTitle("Mon premier formulaire");
   // Fensterabmessungen
   this.setSize(new Dimension(300,100));
}//Konstruktor
  
// Testfunktion
 public static void main(String[] args) {
   // Nachverfolgung
   System.out.println("Début du thread main");
   // Das Formular wird angezeigt
   new form1().setVisible(true);
   // Nachverfolgung
   System.out.println("Fin du thread main");  
}//Hauptprogramm
}//Klasse

Die Ausführung liefert folgende Ergebnisse:

Image

Man kann feststellen, dass der Thread main beendet ist, während das Fenster noch angezeigt wird. Das Schließen des Fensters beendet nicht den Thread, in dem es ausgeführt wurde. Um diesen Thread zu beenden, drückt man erneut Strg+C im DOS-Fenster.

Zum Abschluss dieses Beispiels seien noch die importierten Pakete aufgeführt:

  • javax.swing für die Klasse JFrame
  • java.awt für die Klasse Dimension

5.1.2. Ein Ereignis verarbeiten

Im vorherigen Beispiel müssten wir das Schließen des Fensters selbst handhaben, damit die Anwendung beendet wird, sobald dies geschieht – was derzeit noch nicht der Fall ist. Dazu müssen wir ein Objekt erstellen, das die im Fenster auftretenden Ereignisse „abhört“ und das Ereignis „Fenster schließen“ erkennt. Dieses Objekt wird als „Listener“ oder Ereignisbehandler bezeichnet. Es gibt verschiedene Arten von Ereignisbehandlern für die unterschiedlichen Ereignisse, die an den Komponenten einer grafischen Benutzeroberfläche auftreten können. Für die Komponente JFrame heißt der Listener WindowListener und ist eine Schnittstelle, die die folgenden Methoden definiert (siehe Java-Dokumentation)

Methodenzusammenfassung
 
void
windowActivated(WindowEvent e)
          Das Fenster wird zum aktiven Fenster
 
void
windowClosed(WindowEvent e)
          Das Fenster wurde geschlossen
 
void
windowClosing(WindowEvent e)
          Der Benutzer oder das Programm hat das Schließen des Fensters angefordert
 
void
windowDeactivated(WindowEvent e)
          Das Fenster ist nicht mehr das aktive Fenster
 
void
windowDeiconified(WindowEvent e)
          Das Fenster wechselt vom minimierten in den normalen Zustand
 
void
windowIconified(WindowEvent e)
          Das Fenster wechselt vom normalen Zustand in den minimierten Zustand
 
void
windowOpened(WindowEvent e)
          Das Fenster wird zum ersten Mal sichtbar
 

Es gibt also sieben Ereignisse, die abgehandelt werden können. Die Handler erhalten alle als Parameter ein Objekt vom Typ WindowEvent, das wir vorerst ignorieren. Das Ereignis, das uns hier interessiert, ist das Schließen des Fensters, ein Ereignis, das von der Methode windowClosing verarbeitet werden muss. Um dieses Ereignis zu behandeln, können wir mithilfe einer anonymen Klasse wie folgt ein Objekt vom Typ Windowlistener erstellen:


   // Erstellung eines Ereignis-Handlers
   WindowListener win=new WindowListener(){
     public void windowActivated(WindowEvent e){}
     public void windowClosed(WindowEvent e){}
     public void windowClosing(WindowEvent e){System.exit(0);}
     public void windowDeactivated(WindowEvent e){}
     public void windowDeiconified(WindowEvent e){}
     public void windowIconified(WindowEvent e){}
     public void windowOpened(WindowEvent e){}
   };//Win-Definition

Unser Ereignismanager, der die Schnittstelle WindowListener implementiert, muss die sieben Methoden dieser Schnittstelle definieren. Da wir nur das Schließen des Fensters behandeln wollen, definieren wir nur Code für die Methode windowClosing. Wenn die anderen Ereignisse eintreten, werden wir darüber benachrichtigt, unternehmen aber nichts. Was tun wir, wenn wir darüber benachrichtigt werden, dass das Fenster gerade geschlossen wird (windowClosing)? Wir beenden die Anwendung:


     public void windowClosing(WindowEvent e){System.exit(0);}

Wir haben hier ein Objekt, das die Ereignisse eines Fensters im Allgemeinen verarbeiten kann. Wie ordnen wir es einem bestimmten Fenster zu? Die Klasse JFrame verfügt über eine Methode addWindowListener(WindowListener win), mit der ein „Fenster“-Ereignishandler einem bestimmten Fenster zugeordnet werden kann. Hier schreiben wir also im Konstruktor des Fensters:


   // Erstellung eines Ereignis-Handlers
   WindowListener win=new WindowListener(){
     public void windowActivated(WindowEvent e){}
     public void windowClosed(WindowEvent e){}
     public void windowClosing(WindowEvent e){System.exit(0);}
     public void windowDeactivated(WindowEvent e){}
     public void windowDeiconified(WindowEvent e){}
     public void windowIconified(WindowEvent e){}
     public void windowOpened(WindowEvent e){}
   };//Windows-Definition
    // Dieser Ereignismanager verwaltet die Ereignisse des aktuellen Fensters
   this.addWindowListener(win);

Das vollständige Programm lautet wie folgt:


// Importierte Klassen
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.awt.event.*;

// Die Formularklasse
 public class form2 extends JFrame {
    
// der Konstruktor
 public form2() {
   // Fenstertitel
   this.setTitle("Mon premier formulaire");
   // Fensterabmessungen
   this.setSize(new Dimension(300,100));
   // Erstellung eines Ereignishandlers
   WindowListener win=new WindowListener(){
     public void windowActivated(WindowEvent e){}
     public void windowClosed(WindowEvent e){}
     public void windowClosing(WindowEvent e){System.exit(0);}
     public void windowDeactivated(WindowEvent e){}
     public void windowDeiconified(WindowEvent e){}
     public void windowIconified(WindowEvent e){}
     public void windowOpened(WindowEvent e){}
   };//Win-Definition
   // Dieser Ereignis-Handler verwaltet die Ereignisse des aktuellen Fensters
   this.addWindowListener(win);
}//Konstruktor
  
// Testfunktion
 public static void main(String[] args) {
   // Das Formular wird angezeigt
   new form2().setVisible(true);
}//main
}//Klasse

Das Paket java.awt.event enthält die Schnittstelle WindowListener. Wenn man dieses Programm ausführt und das angezeigte Fenster schließt, wird im DOS-Fenster, in dem das Programm gestartet wurde, das Ende der Programmausführung angezeigt, was zuvor nicht der Fall war.

In unserem Programm ist die Erstellung des Objekts, das für die Verwaltung der Fensterereignisse zuständig ist, etwas aufwendig, da man gezwungen ist, Methoden auch für Ereignisse zu definieren, die man gar nicht verarbeiten möchte. In diesem Fall kann man anstelle der Schnittstelle WindowListener die Klasse WindowAdapter verwenden. Diese implementiert die Schnittstelle WindowListener mit sieben leeren Methoden. Indem wir die Klasse WindowAdapter ableiten und nur die Methoden neu definieren, die uns interessieren, erzielen wir dasselbe Ergebnis wie mit der Schnittstelle WindowListener, ohne jedoch die Methoden definieren zu müssen, die uns nicht interessieren. Die Reihenfolge

  • Definition des Ereignishandlers
  • Zuordnung des Handlers zum Fenster

kann in unserem Beispiel wie folgt erfolgen:


   // Erstellung eines Ereignishandlers
   WindowAdapter win=new WindowAdapter(){
     public void windowClosing(WindowEvent e){System.exit(0);}
   };//Win-Definition
   // Dieser Ereignis-Handler verwaltet die Ereignisse des aktuellen Fensters
   this.addWindowListener(win);

Wir verwenden hier eine anonyme Klasse, die von der Klasse WindowAdapter abgeleitet ist und deren Methode windowClosing neu definiert. Das Programm sieht dann wie folgt aus:


// importierte Klassen
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.awt.event.*;

// Die Formularklasse
 public class form2 extends JFrame {
    
// der Konstruktor
 public form2() {
   // Fenstertitel
   this.setTitle("Mon premier formulaire");
   // Fensterabmessungen
   this.setSize(new Dimension(300,100));
   // Erstellung eines Ereignishandlers
   WindowAdapter win=new WindowAdapter(){
     public void windowClosing(WindowEvent e){System.exit(0);}
   };//Win-Definition
   // Dieser Ereignis-Handler verwaltet die Ereignisse des aktuellen Fensters
   this.addWindowListener(win); }//Konstruktor
  
// Testfunktion
 public static void main(String[] args) {
   // Das Formular wird angezeigt
   new form2().setVisible(true);
}//main
}//Klasse

Es liefert dieselben Ergebnisse wie das vorherige Programm, ist aber einfacher zu schreiben.

5.1.3. Ein Formular mit Schaltfläche

Fügen wir nun eine Schaltfläche zu unserem Fenster hinzu:


// importierte Klassen
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.awt.event.*;

// die Formularklasse
 public class form3 extends JFrame {
 
     // eine Schaltfläche
  JButton btnTest=null;
  Container conteneur=null;
  
  // der Konstruktor
  public form3() {
     // Fenstertitel
    this.setTitle("Formulaire avec bouton");
     // Fensterabmessungen
    this.setSize(new Dimension(300,100));
    // Erstellung eines Ereignishandlers
    WindowAdapter win=new WindowAdapter(){
     public void windowClosing(WindowEvent e){System.exit(0);}
    };//Win-Definition
     // Dieser Ereignis-Handler verwaltet die Ereignisse des aktuellen Fensters
    this.addWindowListener(win);
     // Wir rufen den Container des Fensters ab
    conteneur=this.getContentPane();
     // Wir wählen einen Layout-Manager für die Komponenten in diesem Container aus
    conteneur.setLayout(new FlowLayout());
    // Es wird eine Schaltfläche erstellt
    btnTest=new JButton();
    // Die Beschriftung der Schaltfläche wird festgelegt
    btnTest.setText("Test");
    // Die Schaltfläche wird dem Container hinzugefügt
    conteneur.add(btnTest);
  }//Konstruktor
  
  // Testfunktion
 public static void main(String[] args) {
    // Das Formular wird angezeigt
   new form3().setVisible(true);
}//main
}//Klasse

Ein Fenster JFrame verfügt über einen Container, in den grafische Komponenten (Schaltflächen, Kontrollkästchen, Dropdown-Listen usw.) eingefügt werden können. Dieser Container ist über die Methode getContentPane der Klasse JFrame verfügbar:


  Container conteneur=null;
..........
     // Der Fenstercontainer wird abgerufen
    conteneur=this.getContentPane();

Jede Komponente wird mithilfe der Methode add der Klasse Container in den Container eingefügt. Um also die Komponente C in das zuvor genannte Objekt conteneur einzufügen, schreibt man:

conteneur.add(C)

Wo wird diese Komponente im Container platziert? Es gibt verschiedene Layout-Manager für Komponenten mit dem Namen XXXLayout, wobei beispielsweise XXX mit Border, Flow, ... Jeder Layout-Manager hat seine Besonderheiten. Der Layout-Manager FlowLayout ordnet die Komponenten beispielsweise in Zeilen an, beginnend am oberen Rand des Formulars. Wenn eine Zeile gefüllt ist, werden die Komponenten in die nächste Zeile verschoben. Um einem Fenster JFrame einen Layout-Manager zuzuordnen, verwendet man die Methode setLayout der Klasse JFrame in folgender Form:

    setLayout(objet XXXLayout);

In unserem Beispiel haben wir also, um dem Fenster einen Handler vom Typ FlowLayout zuzuweisen, Folgendes geschrieben:


     // einen Layout-Manager für die Komponenten in diesem Container auswählen
    conteneur.setLayout(new FlowLayout());

Man kann auch auf einen Layout-Handler verzichten und schreiben:

    setLayout(null);

In diesem Fall müssen die genauen Koordinaten der Komponente im Container in der Form (x, y, Breite, Höhe) angegeben werden, wobei (x, y) die Koordinaten der oberen linken Ecke der Komponente im Container sind. Diese Methode werden wir im weiteren Verlauf am häufigsten verwenden.

Wir wissen nun, wie die Komponenten im Container (add) platziert werden und wo (setLayout). Nun müssen wir noch wissen, welche

Komponenten, die in einen Container platziert werden können. Hier platzieren wir eine Schaltfläche, die durch die Klasse javax.swing.JButton modelliert wird:



  JButton btnTest=null;
..........
     // Man erstellt eine Schaltfläche
    btnTest=new JButton();
    // die Beschriftung wird festgelegt
    btnTest.setText("Test");
    // Die Schaltfläche wird dem Container hinzugefügt
    conteneur.add(btnTest);

Wenn man dieses Programm testet, erscheint das folgende Fenster:

Image

Wenn man die Größe des obigen Formulars ändert, wird automatisch der Layout-Manager des Containers aufgerufen, um die Komponenten neu anzuordnen:

Image

Das ist der Hauptvorteil von Layout-Managern: Sie sorgen dafür, dass das Layout der Komponenten auch bei Änderungen der Containergröße konsistent bleibt. Verwenden wir den Layout-Manager null, um den Unterschied zu sehen. Die Schaltfläche wird nun durch die folgenden Anweisungen im Container platziert:


// Man wählt einen Formatierungsmanager für die Komponenten in diesem Container aus
conteneur.setLayout(null);
    // Man erstellt eine Schaltfläche
btnTest=new JButton();
    // Die Beschriftung wird festgelegt
btnTest.setText("Test");
    // Man legt die Position und die Abmessungen fest
btnTest.setBounds(10,20,100,20);
     // Die Schaltfläche wird dem Container hinzugefügt
conteneur.add(btnTest);

Hier wird die Schaltfläche explizit am Punkt (10,20) des Formulars platziert und ihre Abmessungen auf 100 Pixel Breite und 20 Pixel Höhe festgelegt. Das neue Fenster sieht nun wie folgt aus:

Image

Wenn man die Größe des Fensters ändert, bleibt die Schaltfläche an derselben Stelle.

Image

Wenn man auf die Schaltfläche Test klickt, passiert nichts. Das liegt daran, dass wir der Schaltfläche noch keinen Ereignis-Handler zugewiesen haben. Um herauszufinden, welche Arten von Ereignisbehandlungsroutinen für eine bestimmte Komponente verfügbar sind, kann man in der Definition ihrer Klasse nach Methoden wie addXXXListener suchen, mit denen der Komponente eine Ereignisbehandlungsroutine zugewiesen werden kann. Die Klasse javax.swing.JButton leitet sich von der Klasse javax.swing.AbstractButton ab, in der die folgenden Methoden zu finden sind:

Methodenzusammenfassung
 
void
addActionListener(ActionListener l)
 
void
addChangeListener(ChangeListener l)
 
void
addItemListener(ItemListener l)
 

Hier muss man in der Dokumentation nachlesen, welcher Ereignis-Handler den Klick auf die Schaltfläche verarbeitet. Es handelt sich um die Schnittstelle ActionListener. Diese definiert nur eine Methode:

Methodenzusammenfassung
 
void
actionPerformed(ActionEvent e)
 

Die Methode erhält einen Parameter ActionEvent, den wir vorerst ignorieren werden. Um den Klick auf die Schaltfläche btntest in unserem Programm zu verarbeiten, weisen wir ihr zunächst einen Ereignis-Handler zu:


        btnTest.addActionListener(new ActionListener()
         {
                public void actionPerformed(ActionEvent evt){
                  btnTest_clic(evt);
              }
            }//anonyme Klasse
    );//Ereignisbehandler

Hier verweist die Methode actionPerformed auf die Methode btnTest_clic, die wir wie folgt definieren:


public void btnTest_clic(ActionEvent evt){
  // Konsolenüberwachung
System.out.println("clic sur bouton");
}//btnTest_click

Jedes Mal, wenn der Benutzer auf die Schaltfläche Test klickt, wird eine Meldung in die Konsole geschrieben. Dies zeigt die folgende Ausführung:

Image

Das vollständige Programm lautet wie folgt:


// importierte Klassen
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.awt.event.*;

// Formularklasse
 public class form4 extends JFrame {
 
     // eine Schaltfläche
  JButton btnTest=null;
  Container conteneur=null;
  
  // der Konstruktor
  public form4() {
     // Fenstertitel
    this.setTitle("Formulaire avec bouton");
     // Fensterabmessungen
    this.setSize(new Dimension(300,100));
    // Erstellung eines Ereignishandlers
    WindowAdapter win=new WindowAdapter(){
     public void windowClosing(WindowEvent e){System.exit(0);}
    };//Windows-Definition
     // Dieser Ereignis-Handler verwaltet die Ereignisse des aktuellen Fensters
    this.addWindowListener(win);
     // Wir rufen den Container des Fensters ab
    conteneur=this.getContentPane();
     // Wir wählen einen Layout-Manager für die Komponenten in diesem Container aus
    conteneur.setLayout(null);
    // Es wird eine Schaltfläche erstellt
    btnTest=new JButton();
    // Die Beschriftung wird festgelegt
    btnTest.setText("Test");
    // Man legt die Position und die Abmessungen fest
    btnTest.setBounds(10,20,100,20);
     // Man ordnet ihr einen Ereignis-Handler zu
    btnTest.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent evt){
              btnTest_clic(evt);
          }
        }//anonyme Klasse
    );//Ereignisbehandler
     // Die Schaltfläche wird dem Container hinzugefügt
    conteneur.add(btnTest);
  }//Konstruktor

    public void btnTest_clic(ActionEvent evt){
       // Konsolen-Tracking
    System.out.println("clic sur bouton");
  }//btnTest_click
    
  // Testfunktion
 public static void main(String[] args) {
    // Das Formular wird angezeigt
   new form4().setVisible(true);
}//Hauptprogramm
}//Klasse

5.1.4. Ereignisbehandler

Die wichtigsten Swing-Komponenten, die wir vorstellen werden, sind Fenster (JFrame), Schaltflächen (JButton), Kontrollkästchen (JCheckBox), Optionsfelder (JButtonRadio), Dropdown-Listen (JComboBox), Listen (JList), Schieberegler (JScrollBar), Beschriftungen (JLabel), einzeilige (JTextField) oder mehrzeilige (JTextArea) Eingabefelder, Menüs (JMenuBar), Menüelemente (JMenuItem).

Die folgenden Tabellen enthalten eine Liste einiger Ereignisbehandler und der Ereignisse, mit denen sie verknüpft sind.

Handler
Komponente(n)
Registrierungsmethode
Ereignis
ActionListener
JButton, JCheckbox, JButtonRadio, JMenuItem
public void addActionListener(ActionListener)
Klick auf die Schaltfläche, das Kontrollkästchen, das Optionsfeld, das Menüelement
 
JTextField
ItemListener
JComboBox, JList
public void addItemListener(ItemListener)
Das ausgewählte Element hat sich geändert
InputMethodListener
JTextField, JTextArea
public void addMethodInputListener(InputMethodListener)
Der Text im Eingabefeld hat sich geändert oder die Position des Eingabecursors hat sich geändert
CaretListener
JTextField, JTextArea
public void addcaretListener(CaretListener)
Die Position des Eingabecursors hat sich geändert
AdjustmentListener
JScrollBar
public void addAdjustmentListener(AdjustmentListener)
Der Wert des Reglers hat sich geändert
MouseMotionListener
 
public void addMouseMotionListener(MouseMotionListener)
Die Maus wurde bewegt
WindowListener
JFrame
public void addWindowlistener(WindowListener)
Fensterereignis
MouseListener
 
public void addMouselistener(MouseListener)
Mausereignisse (Klick, Ein-/Austritt aus dem Bereich einer Komponente, Taste gedrückt, losgelassen)
FocusListener
 
public void addFocuslistener(FocusListener)
Ereignis „Focus“ (erhalten, verloren)
KeyListener
 
public void addKeylistener(KeyListener)
Tastaturereignis (Taste getippt, gedrückt, losgelassen)
Komponente
Methode zum Registrieren von Ereignisbehandlungsroutinen
JButton
public void addActionListener(ActionListener)
JCheckbox
public void addItemListener(ItemListener)
JCheckboxMenuItem
public void addItemListener(ItemListener)
JComboBox
public void addItemListener(ItemListener)
public void addActionListener(ActionListener)
Container
public void addContainerListener(ContainerListener)
JComponent
public void addComponentListener(ComponentListener)
public void addFocusListener(FocusListener)
public void addKeyListener(KeyListener)
public void addMouseListener(MouseListener)
public void addMouseMotionListener(MouseMotionListener)
JFrame
public void addWindowlistener(WindowListener)
JList
public void addItemListener(ItemListener)
JMenuItem
public void addActionListener(ActionListener)
JPanel
als Container
JScrollPane
als Container
JScrollBar
public void addAdjustmentListener(AdjustmentListener)
JTextComponent
public void addInputMethodListener(InputMethodListener)
public void addCaretListener(CaretListener)
JTextArea
wie JTextComponent
JTextField
wie JTextComponent
public void addActionListener(ActionListener)

Alle Komponenten, mit Ausnahme derjenigen vom Typ TextXXX, sind von der Klasse JComponent abgeleitet und verfügen daher ebenfalls über die dieser Klasse zugeordneten Methoden.

5.1.5. Die Methoden der Ereignisbehandler

Die folgende Tabelle listet die Methoden auf, die von den verschiedenen Ereignisbehandlungsroutinen implementiert werden müssen.

Schnittstelle
Methoden
ActionListener
public void actionPerformed(ActionEvent)
AdjustmentListener
public void adjustmentValueChanged(AdjustmentEvent)
ComponentListener
public void componentHidden(ComponentEvent)
public void componentMoved(ComponentEvent)
public void componentResized(ComponentEvent)
public void componentShown(ComponentEvent)
ContainerListener
public void componentAdded(ContainerEvent)
public void componentRemoved(ContainerEvent)
FocusListener
public void focusGained(FocusEvent)
public void focusLost(FocusEvent)
ItemListener
public void itemStateChanged(ItemEvent)
KeyListener
public void keyPressed(KeyEvent)
public void keyReleased(KeyEvent)
public void keyTyped(KeyEvent)
MouseListener
public void mouseClicked(MouseEvent)
public void mouseEntered(MouseEvent)
public void mouseExited(MouseEvent)
public void mousePressed(MouseEvent)
public void mouseReleased(MouseEvent)
MouseMotionListener
public void mouseDragged(MouseEvent)
public void mouseMoved(MouseEvent)
TextListener
public void textValueChanged(TextEvent)
InputmethodListener
public void InputMethodTextChanged(InputMethodEvent)
public void caretPositionChanged(InputMethodEvent)
CaretLisetner
public void caretUpdate(CaretEvent)
WindowListener
public void windowActivated(WindowEvent)
public void windowClosed(WindowEvent)
public void windowClosing(WindowEvent)
public void windowDeactivated(WindowEvent)
public void windowDeiconified(WindowEvent)
public void windowIconified(WindowEvent)
public void windowOpened(WindowEvent)

5.1.6. Die Adapterklassen

Wie wir bereits bei der Schnittstelle WindowListener gesehen haben, gibt es Klassen mit dem Namen XXXAdapter, die die Schnittstellen XXXListener mit leeren Methoden implementieren. Ein von einer Klasse XXXAdapter abgeleiteter Ereignisbehandler kann dann nur einen Teil der Methoden der Schnittstelle XXXListener implementieren, nämlich diejenigen, die die Anwendung benötigt.

Angenommen, man möchte Mausklicks auf einer Frame-Komponente f1 verarbeiten. Man könnte ihr einen Ereignis-Handler wie folgt zuweisen:

    f1.addMouseListener(new gestionnaireSouris());

und schreiben:


    public class gestionnaireSouris implements MouseListener{
         // die 5 Methoden der Schnittstelle werden geschrieben MouseListener
        // mouseClicked, ..., mouseReleased)
    }// Ende der Klasse

Da wir jedoch nur Mausklicks verarbeiten möchten, ist es besser, Folgendes zu schreiben:


public class gestionnaireSouris extends MouseAdapter{
        // Man schreibt nur eine einzige Methode, nämlich die, die die Mausklicks verarbeitet
        public void mouseClicked(MouseEvent evt){

        }
}// Ende der Klasse

Die folgende Tabelle listet die Adapterklassen der verschiedenen Ereignisbehandler auf:

Ereignis-Handler
Adapter
ComponentListener
ComponentAdapter
ContainerListener
ContainerAdapter
FocusListener
FocusAdapter
KeyListener
KeyAdapter
MouseListener
MouseAdapter
MouseMotionListener
MouseMotionAdapter
WindowListener
WindowAdapter

5.1.7. Fazit

Wir haben soeben die Grundkonzepte der Erstellung grafischer Benutzeroberflächen in Java vorgestellt:

  • Erstellung eines Fensters
  • Erstellung von Komponenten
  • Zuordnung der Komponenten zum Fenster mithilfe eines Layout-Managers
  • Zuordnung von Ereignisbehandlungsroutinen zu den Komponenten

Anstatt nun grafische Benutzeroberflächen wie gerade beschrieben „von Hand“ zu erstellen, werden wir JBuilder verwenden, ein Java-Entwicklungstool von Borland/Inprise in der Version 4, und die Komponenten aus der Bibliothek supérieure.Nous nutzen, die derzeit von Sun, dem Entwickler von Java, empfohlen wird.

5.2. Erstellen einer grafischen Benutzeroberfläche mit JBuilder

5.2.1. Unser erstes JBuilder-Projekt

Um uns mit JBuilder vertraut zu machen, erstellen wir eine ganz einfache Anwendung: ein leeres Fenster.

  1. Starten Sie JBuilder und wählen Sie die Option „Datei/Neues Projekt“. Daraufhin wird die erste Seite eines Assistenten angezeigt:

Image

  1. Füllen Sie die folgenden Felder aus:
Projektname
Start
Dadurch wird eine Projektdatei mit dem Namen début.jpr in dem Ordner erstellt, der im Feld „Name des Projektverzeichnisses“ angegeben ist
Stammverzeichnis
Geben Sie den Ordner an, unter dem der Ordner für das von Ihnen zu erstellende Projekt angelegt werden soll.
Name des Projektverzeichnisses
Geben Sie den Namen des Ordners an, in dem alle Projektdateien abgelegt werden sollen. Dieser Ordner wird in dem Verzeichnis erstellt, das im Feld „Stammverzeichnis“ angegeben ist

Die Quelldateien (.java, .html, ...), die Zieldateien (.class, ...) und die Sicherungsdateien können in unterschiedlichen Verzeichnissen abgelegt werden. Wenn Sie die entsprechenden Felder leer lassen, werden sie im selben Verzeichnis wie das Projekt abgelegt.

Geben Sie „[suivant]“ ein

  1. Ein Bildschirm bestätigt die Auswahl aus dem vorherigen Schritt

Image

Führen Sie [suivant] aus

  1. Ein neuer Bildschirm fordert Sie auf, Ihr Projekt zu beschreiben:

Image

Führen Sie [terminer] aus

  1. Stellen Sie sicher, dass die Option Voir/projet aktiviert ist. Im linken Fenster sollte nun die Struktur Ihres Projekts angezeigt werden.

Image

  1. Erstellen wir nun eine grafische Benutzeroberfläche in diesem Projekt. Wählen Sie die Option Fichier/Nouveau/Application:

Image

Im Feld classe geben Sie den Namen der Klasse ein, die erstellt werden soll. Hier haben wir denselben Namen wie das Projekt verwendet.

Führen Sie [suivant] aus

  1. Der folgende Bildschirm erscheint:

Image

Klasse
interfaceDébut
Dies ist der Name der Klasse, die dem Fenster entspricht, das erstellt werden soll
Titel
Dies ist der Text, der in der Titelleiste des Fensters angezeigt wird

Beachten Sie, dass wir oben festgelegt haben, dass das Fenster beim Start der Anwendung auf dem Bildschirm zentriert werden soll.

Erstellen Sie [Terminer]

  1. Jetzt erweist sich JBuilder als nützlich.
  • Es generiert die .java-Quelldateien der beiden Klassen, deren Namen wir angegeben haben: die Anwendungsklasse und die Klasse der grafischen Benutzeroberfläche. Diese beiden Dateien erscheinen in der Projektstruktur im linken Fenster

Image

  • Um auf den generierten Code für die beiden Klassen zuzugreifen, genügt ein Doppelklick auf die entsprechende .java-Datei. Wir werden später noch auf den generierten Code zurückkommen.
  • Stellen Sie sicher, dass die Option Voir/Structure aktiviert ist. Damit können Sie die Struktur der aktuell ausgewählten Klasse anzeigen (Doppelklick auf die .java-Datei). Hier sehen Sie beispielsweise die Struktur der Klasse début:

Image

Hier erfahren Sie:

  • welche Bibliotheken importiert wurden (imports)

  • dass es einen Konstruktor début() gibt

  • dass es eine statische Methode main() gibt

  • dass es ein Attribut packFrame gibt

Was ist der Vorteil, Zugriff auf die Struktur einer Klasse zu haben?

  • Sie erhalten einen Überblick darüber. Das ist nützlich, wenn Ihre Klasse komplex ist.

  • Sie können auf den Code einer Methode zugreifen, indem Sie im Strukturfenster der Klasse darauf klicken. Auch dies ist nützlich, wenn Ihre Klasse Hunderte von Zeilen umfasst. Sie müssen nicht alle Zeilen durchgehen, um den gesuchten Code zu finden.

Der von JBuilder generierte Code ist bereits einsatzbereit. Wählen Sie „Ausführen/Projekt ausführen“ oder „F9“, und Sie erhalten das gewünschte Fenster:

Image

Außerdem wird es ordnungsgemäß geschlossen, wenn man auf die Schaltfläche zum Schließen des Fensters klickt. Wir haben soeben unsere erste grafische Benutzeroberfläche erstellt. Wir können unser Projekt über die Option „Datei/Projekte schließen“ speichern:

Image

Wenn Sie auf Tous drücken, werden alle im obigen Fenster angezeigten Projekte markiert. OK schließt sie. Wenn wir neugierig sind und mit dem Windows-Explorer in den Ordner unseres Projekts wechseln (den wir dem Assistenten zu Beginn der Projektkonfiguration angegeben haben), finden wir dort die folgenden Dateien:

Image

In unserem Beispiel hatten wir festgelegt, dass sich alle Dateien (Quelldatei .java, Zieldatei .class, Sicherungsdatei .jpr~) im selben Ordner wie die Projektdatei .jpr befinden sollen.

5.2.2. Die von JBuilder für eine grafische Benutzeroberfläche generierten Dateien

Schauen wir uns nun einmal an, welche .java-Quelldateien JBuilder generiert hat. Es ist wichtig, die generierten Dateien lesen zu können, da wir meistens Code zu dem Hinzufügen müssen, was generiert wurde. Beginnen wir damit, unser Projekt zu öffnen: „Datei“ > „Projekt öffnen“ und wählen wir das Projekt „début.jpr“ aus. Wir finden das zuvor erstellte Projekt wieder.

5.2.2.1. Die Hauptklasse

Sehen wir uns die Klasse „début.java“ an, indem wir im Fenster mit der Liste der Projektdateien auf ihren Namen doppelklicken. Wir erhalten folgenden Code:

import javax.swing.UIManager;
import java.awt.*;

public class début {
  boolean packFrame = false;

   /**Anwendung erstellen*/
  public début() {
    interfaceDébut frame = new interfaceDébut();

     //Rahmen mit vordefinierten Größen validieren
     //Rahmen mit bevorzugten Größenangaben komprimieren – z. B. anhand ihres Layouts
    if (packFrame) {
      frame.pack();
    }
    else {
      frame.validate();
    }
    //Fenster zentrieren
    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    Dimension frameSize = frame.getSize();
    if (frameSize.height > screenSize.height) {
      frameSize.height = screenSize.height;
    }
    if (frameSize.width > screenSize.width) {
      frameSize.width = screenSize.width;
    }
    frame.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2);
    frame.setVisible(true);
  }
   /**Hauptmethode*/
  public static void main(String[] args) {
    try {
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    }
    catch(Exception e) {
      e.printStackTrace();
    }
    new début();
  }
}

Erläutern wir den generierten Code:

  1. Die Funktion main legt das Erscheinungsbild des Fensters (setLookAndFeel) fest und erstellt eine Instanz der Klasse début.
  2. Anschließend wird der Konstruktor début() ausgeführt. Er erstellt eine Instanz frame der Fensterklasse (new interfaceDébut()). Diese wird instanziiert, aber nicht angezeigt.
  3. Das Fenster wird dann entsprechend den für die einzelnen Fensterkomponenten verfügbaren Informationen dimensioniert (frame.validate). Es beginnt nun sein eigenständiges Dasein, indem es angezeigt wird und auf Benutzeraktionen reagiert.
  4. Das Fenster wird auf dem Bildschirm zentriert, da dies bei der Konfiguration des Fensters mit dem Assistenten festgelegt wurde.

Schauen wir uns an, was dabei herauskäme, wenn wir den Code début.java auf das absolute Minimum reduzieren würden, wie wir es zu Beginn des Kapitels getan haben. Erstellen wir eine neue Klasse. Wählen Sie die Option „Datei/Neue Klasse“:

Image

Benennen Sie die neue Klasse in „début2“ um und erstellen Sie „[Terminer]“. Im Projekt erscheint eine neue Datei:

Image

Die Datei „début2.java“ wird auf das Wesentliche reduziert:

public class début2 {
}

Ergänzen wir die Klasse wie folgt:

public class début2 {
   // Hauptfunktion
  public static void main(String args[]){
    // Erstellt das Fenster
    new interfaceDébut().show();    // oder new interfaceDébut.setVisible(true);
  }//main
}//Klasse „début2“

Die Funktion main erstellt eine Instanz des Fensters interfaceDébut und zeigt diese an (show). Bevor wir unser Projekt ausführen, müssen wir darauf hinweisen, dass die Klasse, die die auszuführende Funktion main enthält, nun die Klasse début2 ist. Klicken Sie mit der rechten Maustaste auf das Projekt début.jpr und wählen Sie die Option propriétés sowie anschließend die Registerkarte Exécution:

21

Image

Hier wird angezeigt, dass die Hauptklasse début ist (1). Klicken Sie auf die Schaltfläche (2), um eine andere Hauptklasse auszuwählen:

Image

Wählen Sie „début2“ aus und ändern Sie den Wert auf „[OK]“.

Image

Geben Sie [OK] ein, um diese Auswahl zu bestätigen, und starten Sie anschließend das Projekt über „Ausführen/Projekt ausführen“ oder F9. Sie erhalten dasselbe Fenster wie bei der Klasse début, nur dass es nicht zentriert ist, da dies hier nicht angefordert wurde. Im weiteren Verlauf werden wir die von JBuilder generierte Hauptklasse nicht mehr vorstellen, da sie immer dasselbe tut: ein Fenster erstellen. Wir werden uns fortan auf die Klasse dieses Fensters konzentrieren.

5.2.2.2. Die Fensterklasse

Sehen wir uns nun den Code an, der für die Klasse interfaceDébut generiert wurde:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class interfaceDébut extends JFrame {
  JPanel contentPane;
  BorderLayout borderLayout1 = new BorderLayout();

  /**Rahmen erstellen*/
  public interfaceDébut() {
    enableEvents(AWTEvent.WINDOW_EVENT_MASK);
    try {
      jbInit();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  }
   /**Komponente initialisieren*/
  private void jbInit() throws Exception  {
    contentPane = (JPanel) this.getContentPane();
    contentPane.setLayout(borderLayout1);
    this.setSize(new Dimension(400, 300));
    this.setTitle("Ma première interface graphique avec Jbuilder");
  }
   /**Ersetzt, damit wir das Programm beenden können, wenn das Fenster geschlossen wird*/
  protected void processWindowEvent(WindowEvent e) {
    super.processWindowEvent(e);
    if (e.getID() == WindowEvent.WINDOW_CLOSING) {
      System.exit(0);
    }
  }
}

5.2.2.2.1. Die importierten Bibliotheken
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

Es handelt sich um die Bibliotheken java.awt, java.awt.event und javax.swing. Die ersten beiden waren die einzigen, die für die Erstellung grafischer Benutzeroberflächen mit den ersten Java-Versionen zur Verfügung standen. Die Bibliothek javax.swing ist neuer. Hier wird sie für das Fenster vom Typ JFrame benötigt, das hier verwendet wird.

5.2.2.2.2. Die Attribute
  JPanel contentPane;
  BorderLayout borderLayout1 = new BorderLayout();

JPanel ist ein Containertyp, in den Komponenten eingefügt werden können. BorderLayout ist einer der verfügbaren Layout-Manager-Typen, um die Komponenten im Container zu platzieren. In allen unseren Beispielen werden wir keinen Layout-Manager verwenden und die Komponenten selbst an einer bestimmten Stelle im Container platzieren. Dazu verwenden wir den Layout-Manager null.

5.2.2.2.3. Der Fenster-Konstruktor
   /**Rahmen erstellen*/
  public interfaceDébut() {
    enableEvents(AWTEvent.WINDOW_EVENT_MASK);
    try {
      jbInit();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  }
   /**Komponente initialisieren*/
  private void jbInit() throws Exception  {
    contentPane = (JPanel) this.getContentPane();
    contentPane.setLayout(borderLayout1);
    this.setSize(new Dimension(400, 300));
    this.setTitle("Ma première interface graphique avec Jbuilder");
  }
  1. Der Hersteller gibt zunächst an, dass er die Ereignisse im Fenster (enableEvents) verarbeiten wird, und ruft dann die Methode jbInit auf.
  2. Der Container (JPanel) des Fensters (JFrame) wird abgerufen (getContentPane)
  3. Der Formatierungsmanager wird festgelegt (setLayout)
  4. Die Fenstergröße wird festgelegt (setSize)
  5. Der Fenstertitel wird festgelegt (setTitle)

5.2.2.2.4. Der Ereignismanager
   /**Ersetzt, damit wir das Programm beenden können, wenn das Fenster geschlossen wird*/
  protected void processWindowEvent(WindowEvent e) {
    super.processWindowEvent(e);
    if (e.getID() == WindowEvent.WINDOW_CLOSING) {
      System.exit(0);
    }

Der Hersteller hatte angegeben, dass die Klasse die Ereignisse des Fensters verarbeiten würde. Diese Aufgabe übernimmt die Methode processWindowEvent. Zunächst leitet sie das empfangene Ereignis WindowEvent an ihre übergeordnete Klasse (JFrame) weiter. Handelt es sich dabei um das Ereignis WINDOW_CLOSING, das durch einen Klick auf die Schaltfläche zum Schließen des Fensters ausgelöst wurde, wird die Anwendung beendet.

5.2.2.2.5. Fazit

Der Code der Fensterklasse unterscheidet sich von dem im Beispiel zu Beginn des Kapitels vorgestellten. Würden wir ein anderes Java-Generierungstool als JBuilder verwenden, hätten wir zweifellos einen noch anderen Code. In der Praxis akzeptieren wir den von JBuilder erzeugten Code zum Erstellen des Fensters, um uns ausschließlich auf das Schreiben der Ereignisbehandler der grafischen Benutzeroberfläche zu konzentrieren.

5.2.3. Eine grafische Benutzeroberfläche zeichnen

5.2.3.1. Ein Beispiel

Im vorherigen Beispiel hatten wir keine Komponenten in das Fenster eingefügt. Erstellen wir nun ein Fenster mit einer Schaltfläche, einem Beschriftungsfeld und einem Eingabefeld:

Image

Die Felder lauten wie folgt:

Nr.
Name
Typ
Rolle
1
lblSaisie
JLabel
eine Bezeichnung
2
txtSaisie
JTextField
ein Eingabefeld
3
cmdAfficher
JButton
um den Inhalt des Eingabefelds in einem Dialogfeld anzuzeigen txtSaisie

Gehen Sie wie beim vorherigen Projekt vor und erstellen Sie das Projekt interface2.jpr, ohne vorerst Komponenten in das Fenster einzufügen.

Image

Wählen Sie im obigen Fenster die Klasse interface2.java aus. Rechts neben diesem Fenster befindet sich eine Registerkarte:

Image

Die Registerkarte „Source“ bietet Zugriff auf den Quellcode der Klasse „interface2.java“. Über die Registerkarte „Conception“ können Sie das Fenster visuell erstellen. Wählen Sie diese Registerkarte aus. Vor Ihnen sehen Sie den Fenstercontainer, in den Sie die Komponenten einfügen werden. Er ist derzeit noch leer. Im linken Fenster wird die Struktur der Klasse angezeigt:

Image

this
steht für das Fenster
contentPane
sein Container, in den Komponenten abgelegt werden, sowie die Art und Weise, wie diese Komponenten im Container angeordnet werden (standardmäßig BorderLayout)
borderLayout1
eine Instanz des Formatierungsmanagers

Wählen Sie das Objekt this aus. Das zugehörige Eigenschaftenfenster wird daraufhin auf der rechten Seite angezeigt:

Image

Einige dieser Eigenschaften sind besonders zu beachten:

background
zur Festlegung der Hintergrundfarbe des Fensters
foreground
zum Festlegen der Farbe der Grafiken im Fenster
JMenuBar
um dem Fenster ein Menü zuzuordnen
title
um dem Fenster einen Titel zu geben
resizable
um den Fenstertyp festzulegen
font
um die Schriftart für die Texte im Fenster festzulegen

Da das Objekt „this“ weiterhin ausgewählt ist, kann man die Größe des auf dem Bildschirm angezeigten Containers ändern, indem man an den Ankerpunkten rund um den Container zieht:

Image

Wir sind nun bereit, Komponenten in den oben genannten Container abzulegen. Zuvor ändern wir jedoch den Formatierungsmanager. Wählen Sie das Objekt contentPane im Strukturfenster aus:

Image

Wählen Sie anschließend im Eigenschaftenfenster dieses Objekts die Eigenschaft layout aus und wählen Sie aus den möglichen Werten den Wert null aus:

Image

Da kein Formatierungsmanager vorhanden ist, können wir die Komponenten frei im Container platzieren. Nun ist es an der Zeit, diese auszuwählen.

Wenn der Bereich „Conception“ ausgewählt ist, stehen die Komponenten in einer Registerkartenleiste am oberen Rand des Entwurfsfensters zur Verfügung:

Image

Zum Erstellen der grafischen Benutzeroberfläche stehen uns Komponenten vom Typ swing (1) und awt (2) zur Verfügung. Wir werden hier die Komponenten vom Typ swing verwenden. Wählen Sie in der obigen Komponentenleiste eine Komponente JLabel (3), eine Komponente JTextField (4) und eine Komponente JButton (5) aus und platzieren Sie diese im Container des Entwurfsfensters.

Image

Nun passen wir jede dieser drei Komponenten an:

  • das Label (JLabel) jLabel1

Wählen Sie die Komponente aus, um ihr Eigenschaftenfenster zu öffnen. Ändern Sie darin die folgenden Eigenschaften: name: lblSaisie, text: Eingabe

  • das Eingabefeld (JTextField) jTextfield1

Wählen Sie die Komponente aus, um ihr Eigenschaftenfenster zu öffnen. Ändern Sie darin die folgenden Eigenschaften: name: txtSaisie, text: nichts eingeben

  • die Schaltfläche (JButton): name: cmdAfficher, text: Anzeigen

Nun haben wir das folgende Fenster:

Image

und die folgende Struktur:

Image

Wir können (F9) unser Projekt ausführen, um einen ersten Eindruck vom Fenster in Aktion zu erhalten:

Image

Schließen Sie das Fenster. Nun müssen wir noch die Prozedur schreiben, die beim Klicken auf die Schaltfläche Afficher ausgeführt wird. Wählen Sie die Schaltfläche aus, um das Eigenschaftenfenster aufzurufen. Dieses verfügt über zwei Registerkarten: propriétés und événements. Wählen Sie „événements“ aus.

Image

In der linken Spalte des Fensters sind die möglichen Ereignisse für die Schaltfläche aufgelistet. Ein Klick auf eine Schaltfläche entspricht dem Ereignis actionPerformed. Die rechte Spalte enthält den Namen der Prozedur, die aufgerufen wird, wenn das entsprechende Ereignis eintritt. Klicken Sie auf die Zelle rechts neben dem Ereignis actionPerformed:

Image

JBuilder generiert für jeden Ereignis-Handler einen Standardnamen in der Form nomComposant_nomEvénement, hier cmdAfficher_actionPerformed. Man könnte den vorgeschlagenen Standardnamen löschen und einen anderen eingeben. Um auf den Code des Handlers cmdAfficher_actionPerformed zuzugreifen, genügt ein Doppelklick auf den oben genannten Namen. Man gelangt dann automatisch in den Quellcode-Bereich der Klasse, der auf das Grundgerüst des Codes des Ereignis-Handlers ausgerichtet ist:

  void cmdAfficher_actionPerformed(ActionEvent e) {
 }

Nun müssen wir diesen Code nur noch vervollständigen. Hier möchten wir ein Dialogfeld anzeigen, das den Inhalt des Feldes txtSaisie enthält:

  void cmdAfficher_actionPerformed(ActionEvent e) {
    JOptionPane.showMessageDialog(this, "texte saisi="+txtSaisie.getText(), 
"Vérification de la saisie",JOptionPane.INFORMATION_MESSAGE);
 }

JOptionPane ist eine Klasse der Bibliothek javax.swing. Sie ermöglicht es, Meldungen zusammen mit einem Symbol anzuzeigen oder Informationen vom Benutzer abzufragen. Hier verwenden wir eine statische Methode der Klasse:

Image

parentComponent
das „übergeordnete“ Container-Objekt des Dialogfelds: hier this.
Meldung
ein anzuzeigendes Objekt. Hier der Inhalt des Eingabefelds
title
Der Titel des Dialogfelds
messageType
Der Typ der anzuzeigenden Meldung. Bestimmt das Symbol, das im Feld neben der Meldung angezeigt wird. Mögliche Werte:
INFORMATION_MESSAGE, QUESTION_MESSAGE, ERROR_MESSAGE, WARNING_MESSAGE, PLAIN_MESSAGE

Führen wir unsere Anwendung (F9) aus:

Image

Image

5.2.3.2. Der Code der Fensterklasse

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.beans.*;
import javax.swing.event.*;


public class interface2 extends JFrame {
  JPanel contentPane;
  JLabel lblSaisie = new JLabel();
  JTextField txtSaisie = new JTextField();
  JButton cmdAfficher = new JButton();

  /**Rahmen erstellen*/
  public interface2() {
    enableEvents(AWTEvent.WINDOW_EVENT_MASK);
    try {
      jbInit();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  }
   /**Komponente initialisieren*/
  private void jbInit() throws Exception  {
    lblSaisie.setText("Saisie");
    lblSaisie.setBounds(new Rectangle(25, 23, 71, 21));
    contentPane = (JPanel) this.getContentPane();
    contentPane.setLayout(null);
    this.setSize(new Dimension(304, 129));
    this.setTitle("Saisies & boutons - 1");
    txtSaisie.setBounds(new Rectangle(120, 21, 138, 24));
    cmdAfficher.setText("Afficher");
    cmdAfficher.setBounds(new Rectangle(111, 77, 77, 20));
    cmdAfficher.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        cmdAfficher_actionPerformed(e);
      }
    });
    contentPane.add(lblSaisie, null);
    contentPane.add(txtSaisie, null);
    contentPane.add(cmdAfficher, null);
  }
   /**Ersetzt, damit wir das Programm beenden können, wenn das Fenster geschlossen wird*/
  protected void processWindowEvent(WindowEvent e) {
    super.processWindowEvent(e);
    if (e.getID() == WindowEvent.WINDOW_CLOSING) {
      System.exit(0);
    }
  }
  void cmdAfficher_actionPerformed(ActionEvent e) {
    JOptionPane.showMessageDialog(this, "texte saisi="+txtSaisie.getText(), "Vérification de la saisie",JOptionPane.INFORMATION_MESSAGE);
  }
}

5.2.3.2.1. Die Attribute
  JPanel contentPane;
  JLabel lblSaisie = new JLabel();
  JTextField txtSaisie = new JTextField();
  JButton cmdAfficher = new JButton();

Darin befinden sich der Behälter mit den Komponenten vom Typ JPanel sowie die drei Komponenten.

5.2.3.2.2. Der Hersteller
   /**Rahmen erstellen*/
  public interface2() {
    enableEvents(AWTEvent.WINDOW_EVENT_MASK);
    try {
      jbInit();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  }
   /**Komponente initialisieren*/
  private void jbInit() throws Exception  {
    lblSaisie.setText("Saisie");
    lblSaisie.setBounds(new Rectangle(25, 23, 71, 21));
    contentPane = (JPanel) this.getContentPane();
    contentPane.setLayout(null);
    this.setSize(new Dimension(304, 129));
    this.setTitle("Saisies & boutons - 1");
    txtSaisie.setBounds(new Rectangle(120, 21, 138, 24));
    cmdAfficher.setText("Afficher");
    cmdAfficher.setBounds(new Rectangle(111, 77, 77, 20));
    cmdAfficher.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        cmdAfficher_actionPerformed(e);
      }
    });
    contentPane.add(lblSaisie, null);
    contentPane.add(txtSaisie, null);
    contentPane.add(cmdAfficher, null);
  }

Der Konstruktor interface2 ähnelt dem Konstruktor der zuvor untersuchten grafischen Benutzeroberfläche. Unterschiede finden sich in der Methode jbInit: Der Code zum Erstellen des Fensters hängt von den darin platzierten Komponenten ab. Man kann den Code von jbInit übernehmen und eigene Kommentare hinzufügen:

  private void jbInit() throws Exception  {
       // das Fenster selbst (Größe, Titel)
this.setSize(new Dimension(304, 129));
    this.setTitle("Saisies & boutons - 1");
         // der Container für die Komponenten
    contentPane = (JPanel) this.getContentPane();
         // kein Formatierungsmanager für diesen Container
    contentPane.setLayout(null);
         // das Etikett lblSaisie (Bezeichnung, Position, Größe)
         lblSaisie.setText("Saisie");
    lblSaisie.setBounds(new Rectangle(25, 23, 71, 21));
        // das Eingabefeld (Position, Größe)
    txtSaisie.setBounds(new Rectangle(120, 21, 138, 24));
         // die Schaltfläche „Anzeigen“ (Bezeichnung, Position, Größe)
    cmdAfficher.setText("Afficher");
    cmdAfficher.setBounds(new Rectangle(111, 77, 77, 20));
         // der Ereignis-Handler der Schaltfläche
    cmdAfficher.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        cmdAfficher_actionPerformed(e);
      }
    });
         // Hinzufügen der 3 Komponenten zum Container
    contentPane.add(lblSaisie, null);
    contentPane.add(txtSaisie, null);
    contentPane.add(cmdAfficher, null);
  }//jbInit

Zwei Punkte sind dabei zu beachten:

  • Dieser Code hätte von Hand geschrieben werden können. Das bedeutet, dass man auf JBuilder verzichten kann, um eine grafische Benutzeroberfläche zu erstellen.
  • die Art und Weise, wie der Ereignishandler der Schaltfläche cmdAfficher festgelegt ist. Der Ereignishandler der Komponente cmdAfficher hätte durch cmdAfficher.addActionListener(new Handler()) deklariert werden, wobei gestionnaire eine Klasse mit einer öffentlichen Methode actionPerformed wäre, die für die Verarbeitung des Klicks auf die Schaltfläche Afficher zuständig ist. Hier verwendet JBuilder als Handler eine Instanz einer anonymen Klasse:
 new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        cmdAfficher_actionPerformed(e);
      }

Es wird eine neue Instanz der Schnittstelle ActionListener erstellt, deren Methode actionPerformed im Anschluss definiert wird. Diese ruft lediglich eine Methode der Klasse interface2 auf. All dies ist lediglich ein Kunstgriff, um die Ereignisbehandlungsprozeduren der Komponenten dieses Fensters in derselben Klasse wie das Fenster selbst zu definieren. Man könnte auch anders vorgehen:

cmdAfficher.addActionListener(this)

was dazu führt, dass die Methode actionPerformed in this, also in der Fensterklasse, gesucht wird. Diese zweite Methode scheint einfacher zu sein, doch die erste hat einen Vorteil: Sie ermöglicht es, unterschiedliche Handler für verschiedene Schaltflächen zu verwenden, während dies bei der zweiten Methode nicht möglich ist. Im letzteren Fall muss nämlich die einzige Methode actionPeformed die Klicks verschiedener Schaltflächen verarbeiten und daher zunächst ermitteln, welche Schaltfläche das Ereignis ausgelöst hat, bevor sie mit der Verarbeitung beginnt.

5.2.3.2.3. Die Ereignisbehandler

Es handelt sich um die bereits behandelten:

   /**Ersetzt, damit wir das Programm beenden können, wenn das Fenster geschlossen wird*/
  protected void processWindowEvent(WindowEvent e) {
    super.processWindowEvent(e);
    if (e.getID() == WindowEvent.WINDOW_CLOSING) {
      System.exit(0);
    }
  }

     // Klick auf die Schaltfläche „Anzeigen“
  void cmdAfficher_actionPerformed(ActionEvent e) {
    JOptionPane.showMessageDialog(this, "texte saisi="+txtSaisie.getText(), "Vérification de la saisie",JOptionPane.INFORMATION_MESSAGE);
  }

5.2.3.3. Conclusion

Aus den beiden untersuchten Projekten lässt sich schließen, dass die Aufgabe des Entwicklers, sobald die grafische Benutzeroberfläche mit JBuilder erstellt wurde, darin besteht, die Ereignisbehandler zu schreiben, die er für diese grafische Benutzeroberfläche verwalten möchte.

5.2.4. Hilfe suchen

Bei Java benötigt man oft Hilfe, insbesondere aufgrund der sehr großen Anzahl verfügbarer Klassen. Hier geben wir einige Hinweise, wie man Hilfe zu einer Klasse finden kann. Wählen Sie im Menü die Option „Hilfe/Hilfethemen“.

Image

Der Hilfebildschirm besteht in der Regel aus zwei Fenstern:

  • das linke, in dem man angibt, wonach man sucht. Es verfügt über drei Registerkarten: Sommaire, Index und Chercher.
  • das rechte Fenster, in dem das Suchergebnis angezeigt wird

Es gibt eine Hilfe zur Verwendung der JBuilder-Hilfe. Wählen Sie in der JBuilder-Hilfe die Option „Hilfe/Verwendung der Hilfe“. Dort wird Ihnen erklärt, wie Sie die Hilfe nutzen können. Beispielsweise werden Ihnen die verschiedenen Komponenten des Hilfe-Viewers vorgestellt:

Image

Sehen wir uns die Seiten Sommaire und Index etwas genauer an.

5.2.4.1. Hilfe: Inhaltsverzeichnis

Image

5.2.4.1.1. Inhaltsverzeichnis: Einführung in Java

Hier finden sich die Grundlagen von Java, aber nicht nur das, wie die Liste der in dieser Option behandelten Themen zeigt:

Image

5.2.4.1.2. Inhaltsverzeichnis: Tutorials

Wenn wir im obigen Inhaltsverzeichnis die Option „Tutorials“ auswählen, zeigt das rechte Fenster eine Liste der verfügbaren Tutorials an:

Image

Die grundlegenden Tutorials sind besonders interessant, um sich mit JBuilder vertraut zu machen. Es gibt noch viele weitere neben den oben vorgestellten, und wenn man eine Anwendung entwickeln möchte, kann es hilfreich sein, vorher zu prüfen, ob es nicht ein Tutorial gibt, das einem dabei helfen könnte.

5.2.4.1.3. Inhaltsverzeichnis: JDK

Wenn man die Option „Java 2 JDK 1.3“ auswählt, erhält man Zugriff auf alle Bibliotheken von JDK. Im Allgemeinen sollte man hier nicht suchen, wenn man Informationen zu einer bestimmten Klasse benötigt und nicht weiß, in welcher Bibliothek sie sich befindet. Diese Option ist jedoch interessant, wenn man sich einen Überblick über die Java-Bibliotheken verschaffen möchte.

5.2.4.2. Hilfe: Index

Wählen Sie in der Hilfe die Registerkarte „Index“ im linken Fenster aus. Mit dieser Option können Sie beispielsweise Hilfe zu einer Klasse finden. Nehmen wir an, Sie möchten die Methoden der Eingabefelder swing und JTextField kennenlernen. Geben Sie „JTextField“ in das Suchfeld ein:

Image

Die Hilfe zeigt die Indexeinträge an, die mit dem eingegebenen Text beginnen:

Image

Nun müssen Sie nur noch auf den Eintrag doppelklicken, der Sie interessiert, in diesem Fall „JTextField class“. Die Hilfe zu dieser Klasse wird dann im rechten Fenster angezeigt:

Image

Sie erhalten nun eine vollständige Beschreibung der Klasse.

5.2.5. Einige Swing-Komponenten

Im Folgenden stellen wir verschiedene Anwendungen vor, bei denen die gängigsten Komponenten swing zum Einsatz kommen, um deren wichtigste Methoden und Eigenschaften kennenzulernen. Für jede Anwendung präsentieren wir die grafische Benutzeroberfläche und den relevanten Code, insbesondere den der Ereignisbehandler.

5.2.5.1. Komponenten JLabel und JTextField

Diese beiden Komponenten haben wir bereits kennengelernt. JLabel ist eine Textkomponente und JTextField eine Eingabefeldkomponente. Ihre beiden wichtigsten Methoden sind

String getText()
, um den Inhalt des Eingabefelds oder den Beschriftungstext abzurufen
void setText(String unTexte)
um unTexte in das Feld oder die Beschriftung einzufügen

Die üblicherweise für JTextField verwendeten Ereignisse sind die folgenden:

actionPerformed
signalisiert, dass der Benutzer den eingegebenen Text bestätigt hat (Enter-Taste)
caretUpdate
signalisiert, dass der Benutzer den Eingabecursor bewegt hat
inputMethodChanged
zeigt an, dass der Benutzer das Eingabefeld geändert hat

Hier ist ein Beispiel, das das Ereignis caretUpdate verwendet, um die Änderungen in einem Eingabefeld zu verfolgen:

Image

Nr.
Typ
Name
Rolle
1
JTextField
txtSaisie
Eingabefeld
2
JTextField
txtControle
zeigt den Text von 1 in Echtzeit an
3
JButton
cmdEffacer
zum Löschen der Felder 1 und 2
4
JButton
cmdQuitter
um die Anwendung zu beenden

Der relevante Code dieser Anwendung lautet wie folgt:

import java.awt.*;
....


public class Cadre1 extends JFrame {
  JPanel contentPane;
  JTextField txtSaisie = new JTextField();
  JLabel jLabel1 = new JLabel();
  JLabel jLabel2 = new JLabel();
  JTextField txtControle = new JTextField();
  JButton CmdEffacer = new JButton();
  JButton CmdQuitter = new JButton();

  /**Rahmen erstellen*/
  public Cadre1() {
    enableEvents(AWTEvent.WINDOW_EVENT_MASK);
    try {
      jbInit();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  }
   /**Komponente initialisieren*/
  private void jbInit() throws Exception  {
    ....
    txtSaisie.addCaretListener(new javax.swing.event.CaretListener() {
      public void caretUpdate(CaretEvent e) {
        txtSaisie_caretUpdate(e);
      }
    });

...
    CmdEffacer.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        CmdEffacer_actionPerformed(e);
      }
    });
...
    CmdQuitter.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        CmdQuitter_actionPerformed(e);
      }
    });
....
}

   /**Ersetzt, damit wir das Programm beenden können, wenn das Fenster geschlossen wird*/
  protected void processWindowEvent(WindowEvent e) {
...
  }

  void txtSaisie_caretUpdate(CaretEvent e) {
         // Der Eingabecursor hat sich bewegt
    txtControle.setText(txtSaisie.getText());
  }

  void CmdQuitter_actionPerformed(ActionEvent e) {
        // Die Anwendung wird beendet
    System.exit(0);
  }

  void CmdEffacer_actionPerformed(ActionEvent e) {
        // Der Inhalt des Eingabefelds wird gelöscht
    txtSaisie.setText("");
  }
}

Hier ein Ausführungsbeispiel:

Image

5.2.5.2. Komponente JComboBox

Image

Image

Eine Komponente vom Typ JComboBox ist eine Dropdown-Liste mit einem Eingabefeld: Der Benutzer kann entweder ein Element aus (2) auswählen oder Text in (1) eingeben. Standardmäßig sind die JComboBox-Komponenten nicht bearbeitbar. Um sie bearbeitbar zu machen, muss die Methode setEditable(true) explizit aufgerufen werden. Um mehr über die Klasse JComboBox zu erfahren, geben Sie JComboBox in den Hilfe-Index ein.

Das Objekt JComboBox kann auf verschiedene Arten instanziiert werden:

new JComboBox()
erstellt ein leeres Kombinationsfeld
new JComboBox (Object[] items)
erstellt ein Kombinationsfeld, das ein Array von Objekten enthält
new JComboBox(Vector items)
dasselbe mit einem Vektor von Objekten

Es mag überraschen, dass ein Kombinationsfeld Objekte enthalten kann, obwohl es üblicherweise Zeichenfolgen enthält. Optisch ist dies der Fall. Wenn ein JComboBox ein Objekt obj enthält, wird die Zeichenfolge obj.toString angezeigt() an. Man erinnere sich daran, dass jedes Objekt eine Methode toString besitzt, die von der Klasse Object geerbt wurde und eine Zeichenkette zurückgibt, die das Objekt „repräsentativ“ darstellt.

Die nützlichen Methoden der Klasse JCombobox sind die folgenden:

void addItem(Object unObjet)
fügt ein Objekt zur Combobox hinzu
int getItemCount()
gibt die Anzahl der Elemente in der Combobox zurück
Object getItemAt(int i)
gibt das Objekt Nr. i aus der Combobox zurück
void insertItemAt(Object unObjet, int i)
fügt unObjet an Position i in das Kombinationsfeld ein
int getSelectedIndex()
gibt die Nummer des in der Combobox ausgewählten Elements zurück
Object getSelectedItem()
gibt das in der Combobox ausgewählte Objekt zurück
void setSelectedIndex(int i)
wählt das Element i aus der Combobox aus
void setSelectedItem(Object unObjet)
wählt das angegebene Objekt aus der Combobox aus
void removeAllItems()
leert das Kombinationsfeld
void removeItemAt(int i)
entfernt das Element Nr. i aus der Combobox
void removeItem(Object unObjet)
entfernt das angegebene Objekt aus der Combobox
void setEditable(boolean val)
macht das Kombinationsfeld bearbeitbar (val=true) oder nicht bearbeitbar (val=false)

Bei der Auswahl eines Elements aus der Dropdown-Liste wird das Ereignis actionPerformed ausgelöst, das genutzt werden kann, um über die Änderung der Auswahl in der Combobox informiert zu werden. In der folgenden Anwendung verwenden wir dieses Ereignis, um das aus der Liste ausgewählte Element anzuzeigen.

Image

Wir zeigen hier nur den relevanten Code des Fensters.

public class Cadre1 extends JFrame {
  JPanel contentPane;
  JComboBox jComboBox1 = new JComboBox();
  JLabel jLabel1 = new JLabel();

   /**Rahmen erstellen*/
  public Cadre1() {
    enableEvents(AWTEvent.WINDOW_EVENT_MASK);
    try {
      jbInit();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
     // Verarbeitung – das Kombinationsfeld wird ausgefüllt
    String[] infos={"un","deux","trois","quatre"};
    for(int i=0;i<infos.length;i++)
      jComboBox1.addItem(infos[i]);
  }
   /**Komponente initialisieren*/
  private void jbInit() throws Exception  {
        ....

    jComboBox1.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        jComboBox1_actionPerformed(e);
      }
    });
       .... 
  }

  void jComboBox1_actionPerformed(ActionEvent e) {
        // Ein neues Element wurde ausgewählt – es wird angezeigt
    JOptionPane.showMessageDialog(this,jComboBox1.getSelectedItem(),
"actionPerformed",JOptionPane.INFORMATION_MESSAGE);
  }

}

5.2.5.3. Komponente JList

Die Swing-Komponente JList ist komplexer als ihr Pendant aus der Bibliothek, awt. Es gibt zwei wesentliche Unterschiede:

  • Der Inhalt der Liste wird von einem anderen Objekt als der Liste selbst verwaltet. Hier verwenden wir ein Objekt DefaultListModel, das wie ein Vector verwendet wird, das jedoch zusätzlich das Objekt JList benachrichtigt, sobald sich sein Inhalt ändert, damit sich auch die visuelle Darstellung der Liste entsprechend ändert.
  • Die Liste ist standardmäßig nicht scrollbar. Man muss die Liste in einen Container ScrollPane einfügen, der das Scrollen ermöglicht.

Im Quellcode kann eine Liste wie folgt definiert werden:

      // Der Vektor der Werte der Liste 
DefaultlistModel valeurs=new DefaultListModel();
// die Liste selbst, der der Vektor ihrer Werte zugeordnet wird
  JList jList1 = new JList(valeurs);
     // der scrollbare Container, in den die Liste eingefügt wird, um eine scrollbare Liste zu erhalten
  JScrollPane jScrollPane1 = new JScrollPane(jList1);

Um die Liste jList1 in den Container jScrollPane1 aufzunehmen, geht der von JBuilder generierte Code anders vor:

  • Deklaration des Containers in den Attributen des Fensters
  JScrollPane jScrollPane1 = new JScrollPane();
  • anschließend wird die Liste im Code von jbInit dem Container zugeordnet
    jScrollPane1.getViewport().add(jList1, null);

Um der oben genannten Liste JList1 Werte hinzuzufügen, müssen diese lediglich in den zugehörigen Wertevektor valeurs eingefügt werden:

    // Liste initialisieren
    for(int i=0;i<10;i++)
      valeurs.addElement(""+i);

und man erhält dann das folgende Fenster:

Image

Wie ist diese Benutzeroberfläche aufgebaut?

  • Man wählt eine Komponente JScrollPane auf der Seite „Swing-Container“ der Komponenten aus und zieht sie in das Fenster, wobei man sie auf die gewünschte Größe anpasst
  • Man wählt eine Komponente JList auf der Seite „Swing“ der Komponenten aus und zieht sie in den Container JScrollPane, dessen gesamten Platz sie nun einnimmt.

Der von JBuilder generierte Code muss leicht überarbeitet werden, um den folgenden Code zu erhalten:

public class interfaceAppli extends JFrame {
  JPanel contentPane;
  JLabel jLabel1 = new JLabel();
  DefaultListModel valeurs=new DefaultListModel();
  JList jList1 = new JList(valeurs);
  JScrollPane jScrollPane1 = new JScrollPane();
  JLabel jLabel2 = new JLabel();


   /**Rahmen erstellen*/
  public interfaceAppli() {
    enableEvents(AWTEvent.WINDOW_EVENT_MASK);
    try {
      jbInit();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
     // Verarbeitung
     // Die Liste wird in den scrollPane eingebunden
    // Liste initialisieren
    for(int i=0;i<10;i++)
      valeurs.addElement(""+i);
  }

   /**Komponente initialisieren*/
  private void jbInit() throws Exception  {
        ....
         // Die Liste jList1 ist dem Container jcrollPane1 zugeordnet
    jScrollPane1.getViewport().add(jList1, null);
  }
   /**Ersetzt, damit wir das Programm beenden können, wenn das Fenster geschlossen wird*/
  protected void processWindowEvent(WindowEvent e) {
        ....
  }
}

Sehen wir uns nun die wichtigsten Methoden der Klasse JList an, indem wir im Hilfeindex nach JList suchen. Das Objekt JList kann auf verschiedene Arten instanziiert werden:

Image

Eine einfache Methode ist die, die wir verwendet haben: Erstellen Sie ein leeres DefaultListModel V und verknüpfen Sie es dann mit der zu erstellenden Liste durch new JList(V). Der Inhalt der Liste wird nicht vom Objekt JList verwaltet, sondern von dem Objekt, das die Werte der Liste enthält. Wenn der Inhalt mithilfe eines Objekts DefaultListModel erstellt wurde, das auf der Klasse Vector basiert, können die Methoden der Klasse Vector verwendet werden, um Elemente zur Liste hinzuzufügen, einzufügen und zu löschen. Eine Liste kann eine Einfach- oder Mehrfachauswahl sein. Dies wird durch die Methode setSelectionMode festgelegt:

Image

Mit getSelectionMode lässt sich der aktuelle Auswahlmodus ermitteln:

Image

Das oder die ausgewählten Elemente können über die folgenden Methoden abgerufen werden:

Image

Mit dem Konstruktor JList(DefaultListModel) können wir einem Vektor von Werten eine Liste zuordnen. Umgekehrt können wir das Objekt DefaultListModel aus einer Liste JList wie folgt abrufen:

Image

Damit wissen wir genug, um die folgende Anwendung zu schreiben:

Image

Dieses Fenster besteht aus folgenden Komponenten:

Nr.
Typ
Name
Funktion
1
JTextField
txtSaisie
Eingabefeld
2
JList
jList1
Liste in einem Container jScrollPane1
3
JList
jList2
Liste in einem Container jScrollPane2
4
JButton
cmd1To2
überträgt die ausgewählten Elemente aus Liste 1 in Liste 2
5
JButton
cmd2To1
führt den umgekehrten Vorgang aus
6
JButton
cmdRaz1
Liste 1 leeren
7
JButton
cmdRaz2
Leert Liste 2

Der Benutzer gibt Text in das Feld (1) ein und bestätigt die Eingabe. Daraufhin wird das Ereignis actionPerformed im Eingabefeld ausgelöst, das dazu dient, den eingegebenen Text in Liste 1 hinzuzufügen. Hier ist der Code für diese erste Funktion:

public class interfaceAppli extends JFrame {
  JPanel contentPane;
  JLabel jLabel1 = new JLabel();
  JLabel jLabel2 = new JLabel();
  JLabel jLabel3 = new JLabel();
  JTextField txtSaisie = new JTextField();
  JButton cmd1To2 = new JButton();
  JButton cmd2To1 = new JButton();
  DefaultListModel v1=new DefaultListModel();
  DefaultListModel v2=new DefaultListModel();
  JList jList1 = new JList(v1);
  JList jList2 = new JList(v2);
  JScrollPane jScrollPane1 = new JScrollPane();
  JScrollPane jScrollPane2 = new JScrollPane();
  JButton cmdRaz1 = new JButton();
  JButton cmdRaz2 = new JButton();
  JLabel jLabel4 = new JLabel();

   /**Rahmen erstellen*/
  public interfaceAppli() {
    enableEvents(AWTEvent.WINDOW_EVENT_MASK);
    try {
      jbInit();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  }//interfaceAppli

   /**Komponente initialisieren*/
  private void jbInit() throws Exception  {
    ...
    txtSaisie.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        txtSaisie_actionPerformed(e);
      }
    });
        ...
         // Jlist1 wird in den Container jScrollPane1 eingefügt
    jScrollPane1.getViewport().add(jList1, null);
        // Jlist2 wird in den Container jScrollPane2 eingefügt
    jScrollPane2.getViewport().add(jList2, null);
        ...
  }
   /**Ersetzt, damit wir das Fenster schließen können, wenn es geschlossen wird*/
  protected void processWindowEvent(WindowEvent e) {
...
  }

  void txtSaisie_actionPerformed(ActionEvent e) {
     // Der eingegebene Text wurde validiert
     // Er wird ohne führende und abschließende Leerzeichen abgerufen
    String texte=txtSaisie.getText().trim();
     // Wenn er leer ist, wird er verworfen
    if(texte.equals("")){
      // Fehlermeldung
      JOptionPane.showMessageDialog(this,"Vous devez taper un texte",
        "Erreur",JOptionPane.WARNING_MESSAGE);
      // Ende
      return;
    }//if
    // wenn er nicht leer ist, wird er zu den Werten in Liste 1 hinzugefügt
    v1.addElement(texte);
     // und das Eingabefeld wird geleert
    txtSaisie.setText("");
  }/// txtSaisie_actionperformed
}//Klasse

Der Code zum Übertragen der ausgewählten Elemente von einer Liste in die andere lautet wie folgt:

  void cmd1To2_actionPerformed(ActionEvent e) {
    // Übertragung der in Liste 1 ausgewählten Elemente in Liste 2
    transfert(jList1,jList2);
  }//cmd1To2

  void cmd2To1_actionPerformed(ActionEvent e) {
    // Übertragung der ausgewählten Elemente aus jList2 nach jList1
      transfert(jList2,jList1);
  }//cmd2TO1

  private void transfert(JList L1, JList L2){
      // Übertragung der in Liste 1 ausgewählten Elemente in Liste 2
       // Das Array mit den Indizes der ausgewählten Elemente wird in L1 abgerufen
      int[] indices=L1.getSelectedIndices();
      // Was ist zu tun?
      if (indices.length==0) return;
      // Die Werte aus L1 werden abgerufen
      DefaultListModel v1=(DefaultListModel)L1.getModel();
      // sowie die aus L2
      DefaultListModel v2=(DefaultListModel)L2.getModel();
      for(int i=indices.length-1;i>=0;i--){
        // Die in L1 ausgewählten Werte werden zu L2 hinzugefügt
        v2.addElement(v1.elementAt(indices[i]));
        // Die aus L1 in L2 kopierten Elemente müssen aus L1 gelöscht werden
        v1.removeElementAt(indices[i]);
      }//für
  }//Übertragung

Der zu den Schaltflächen Raz gehörende Code ist äußerst einfach:

  void cmdRaz1_actionPerformed(ActionEvent e) {
    // Liste 1 leeren
    v1.removeAllElements();
  }//Befehl „Raz1“

  void cmdRaz2_actionPerformed(ActionEvent e) {
    // Liste 2 leeren
    v2.removeAllElements();
  }///Befehl Raz2

5.2.5.4. Kontrollkästchen JCheckBox, Optionsfelder JButtonRadio

Wir wollen die folgende Anwendung schreiben:

Image

Das Fenster enthält folgende Komponenten:

Nr.
Typ
Name
Funktion
1
JButtonRadio
jButtonRadio1
jButtonRadio2
jButtonRadio3
3 Optionsfelder, die zur Gruppe buttonGroup1 gehören
2
JCheckBox
jCheckBox1
jCheckBox2
jCheckBox3
3 Kontrollkästchen
3
JList
jList1
eine Liste in einem Container jScrollPane1
4
ButtonGroup
buttonGroup1
Nicht sichtbare Komponente – dient dazu, die drei Optionsfelder so zu gruppieren, dass beim Aktivieren eines davon die anderen deaktiviert werden.

Eine Gruppe von Optionsfeldern lässt sich wie folgt erstellen:

  • Man platziert die einzelnen Optionsfelder, ohne darauf zu achten, sie zu gruppieren
  • Man fügt in den Container eine Swing-Komponente ButtonGroup ein. Diese Komponente ist nicht sichtbar. Sie erscheint daher nicht im Fenster-Designer. Sie ist jedoch in der Struktur sichtbar:

Image

Oben im Zweig „Autre“ sind die nicht-visuellen Attribute des Fensters zu sehen. Sobald eine Gruppe von Optionsfeldern erstellt wurde, kann man ihr jedes der Optionsfelder zuordnen. Dazu wählt man die Eigenschaften des Optionsfelds aus:

Image

und in der Eigenschaft buttonGroup des Optionsfelds gibt man den Namen der Gruppe ein, in die das Optionsfeld eingefügt werden soll, hier buttonGroup1. Diesen Vorgang wiederholt man für alle drei Optionsfelder.

Die wichtigste Methode für Optionsfelder und Kontrollkästchen ist die Methode isSelected(), die angibt, ob das Kontrollkästchen oder das Optionsfeld aktiviert ist. Der der Komponente zugeordnete Text kann mit getText() abgerufen und mit setText(String unTexte) festgelegt werden. Das Kontrollkästchen bzw. die Optionsschaltfläche kann mit der Methode setSelected(boolean value) aktiviert werden.

Beim Klicken auf ein Optionsfeld oder ein Kontrollkästchen wird das Ereignis actionPerformed ausgelöst. Im folgenden Code nutzen wir dieses Ereignis, um die Wertänderungen bei Optionsfeldern und Kontrollkästchen zu verfolgen:

public class interfaceAppli extends JFrame {
  JPanel contentPane;
  JRadioButton jRadioButton1 = new JRadioButton();
  JRadioButton jRadioButton2 = new JRadioButton();
  JRadioButton jRadioButton3 = new JRadioButton();
  JCheckBox jCheckBox1 = new JCheckBox();
  JCheckBox jCheckBox2 = new JCheckBox();
  JCheckBox jCheckBox3 = new JCheckBox();
  ButtonGroup buttonGroup1 = new ButtonGroup();
  JScrollPane jScrollPane1 = new JScrollPane();
  DefaultListModel valeurs=new DefaultListModel();
  JList jList1 = new JList(valeurs);

   /**Rahmen erstellen*/
  public interfaceAppli() {
    enableEvents(AWTEvent.WINDOW_EVENT_MASK);
    try {
      jbInit();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  }
   /**Komponente initialisieren*/
  private void jbInit() throws Exception  {
    jRadioButton1.setSelected(true);
    jRadioButton1.setText("un");
    jRadioButton1.setBounds(new Rectangle(57, 31, 49, 23));
    jRadioButton1.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        afficheRadioButtons(e);
      }
    });

    jRadioButton2.setBounds(new Rectangle(113, 30, 49, 23));
    jRadioButton2.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        afficheRadioButtons(e);
      }
    });
    jRadioButton2.setText("deux");

    jRadioButton3.setBounds(new Rectangle(168, 30, 49, 23));
    jRadioButton3.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        afficheRadioButtons(e);
      }
    });
    jRadioButton3.setText("trois");

// Die Optionsfelder sind gruppiert
    buttonGroup1.add(jRadioButton1);
    buttonGroup1.add(jRadioButton2);
    buttonGroup1.add(jRadioButton3);

// Kontrollkästchen
    jCheckBox1.setText("A");
    jCheckBox1.setBounds(new Rectangle(58, 69, 32, 17));
    jCheckBox1.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        afficheCases(e);
      }
    });

    jCheckBox2.setBounds(new Rectangle(112, 69, 40, 17));
    jCheckBox2.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        afficheCases(e);
      }
    });
    jCheckBox2.setText("B");

    jCheckBox3.setText("C");
    jCheckBox3.setBounds(new Rectangle(170, 69, 37, 17));
    jCheckBox3.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        afficheCases(e);
      }
    });

    ....
  }
   /**Ersetzt, damit wir das Programm beenden können, wenn das Fenster geschlossen wird*/
  protected void processWindowEvent(WindowEvent e) {
        ...
  }

  private void afficheRadioButtons(ActionEvent e){
     // zeigt die Werte der 3 Optionsfelder an
    valeurs.addElement("boutons radio=("+jRadioButton1.isSelected()+","+
      jRadioButton2.isSelected()+","+jRadioButton3.isSelected()+")");
  }//afficheRadioButtons

  void afficheCases(ActionEvent e) {
     // zeigt die Werte der Kontrollkästchen an
    valeurs.addElement("cases à cocher=["+jCheckBox1.isSelected()+","+
      jCheckBox2.isSelected()+","+jCheckBox3.isSelected()+")");
  }//afficheCases

}//sortiert

Hier ein Ausführungsbeispiel:

Image

5.2.5.5. Komponente JScrollBar

Lassen Sie uns die folgende Anwendung erstellen:

Image

Nr.
Typ
Name
Rolle
1
JScrollBar
jScrollBar1
ein horizontaler Regler
2
JScrollBar
jScrollBar2
ein vertikaler Regler
3
JTextField
txtvaleurHS
zeigt den Wert des horizontalen Reglers 1 an – ermöglicht auch die Festlegung dieses Werts
4
JTextField
txtvaleurVS
zeigt den Wert des vertikalen Reglers 2 an – ermöglicht auch die Festlegung dieses Werts
  • Ein Schieberegler vom Typ JScrollBar ermöglicht es dem Benutzer, einen Wert aus einem Bereich ganzer Zahlen auszuwählen, der durch den „Streifen“ des Schiebereglers symbolisiert wird, auf dem sich ein Cursor bewegt.
  • Bei einem horizontalen Schieberegler stellt das linke Ende den Minimalwert des Bereichs dar, das rechte Ende den Maximalwert und der Schieberegler den aktuell gewählten Wert. Bei einem vertikalen Schieberegler wird der Minimalwert durch das obere Ende und der Maximalwert durch das untere Ende dargestellt. Das Paar (min, max) ist standardmäßig auf (0, 100) gesetzt.
  • Ein Klick auf die Endpunkte des Schiebereglers verändert den Wert um einen Schritt (positiv oder negativ), je nach dem angeklickten Endpunkt, der als unitIncrement bezeichnet wird und standardmäßig den Wert 1 hat.
  • Ein Klick auf beiden Seiten des Schiebereglers verändert den Wert um einen Schritt (positiv oder negativ), je nach dem angeklickten Ende, das als blockIncrement bezeichnet wird und standardmäßig den Wert 10 hat.
  • Diese fünf Werte (min, max, Wert, unitIncrement, blockIncrement) können mit den Methoden getMinimum(), getMaximum(), getValue(), getUnitIncrement() und getBlockIncrement() ermittelt werden, die alle eine Ganzzahl zurückgeben und über die Methoden setMinimum(int min), setMaximum(int max), setValue(int val), setUnitIncrement(int uInc), setBlockIncrement(int bInc)

Bei der Verwendung der Komponente JScrollBar sind einige Punkte zu beachten. Zunächst einmal findet man sie in der Swing-Komponentenleiste:

Image

Wenn man sie auf den Container zieht, ist sie standardmäßig vertikal ausgerichtet. Mit der unten aufgeführten Eigenschaft orientation lässt sie sich horizontal ausrichten:

Image

Im obigen Eigenschaftenblatt sieht man, dass man Zugriff auf die Eigenschaften minimum, maximum, value, unitIncrement, blockIncrement des JScrollbar. Diese können daher bereits beim Entwurf festgelegt werden. Wenn man eine Bildlaufleiste auf dem Container platziert, wird deren „Einstellbereich“ nicht angezeigt:

Image

Dieses Problem lässt sich beheben, indem man der Komponente einen Rahmen zuweist. Dies geschieht über die Eigenschaft border, die verschiedene Werte annehmen kann:

Image

So sieht es beispielsweise mit RaisedBevel aus:

Image

Wenn man auf das obere Ende eines vertikalen Schiebereglers klickt, verringert sich dessen Wert. Dies kann den durchschnittlichen Benutzer überraschen, der normalerweise erwartet, dass der Wert „steigt“. Dieses Problem lässt sich beheben, indem man den Werten unitIncrement und blockIncrement einen negativen Wert zuweist.

Wie lässt sich die Wertentwicklung eines Schiebereglers verfolgen? Wenn sich dessen Wert ändert, wird das Ereignis adjustmentValueChanged ausgelöst. Es reicht aus, diesem Ereignis eine Prozedur zuzuordnen, um über jede Änderung des Wertes des Schiebereglers informiert zu werden.

Image

Der relevante Code unserer Anwendung lautet wie folgt:

....

public class cadreAppli extends JFrame {
  JPanel contentPane;
  JScrollBar jScrollBar1 = new JScrollBar();
  Border border1;
  JTextField txtValeurHS = new JTextField();
  JScrollBar jScrollBar2 = new JScrollBar();
  JTextField txtValeurVS = new JTextField();
  TitledBorder titledBorder1;

   /**Rahmen erstellen*/
  public cadreAppli() {
    enableEvents(AWTEvent.WINDOW_EVENT_MASK);
    try {
      jbInit();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  }
   /**Komponente initialisieren*/
  private void jbInit() throws Exception  {
...

// einen Rahmen für die Bildlaufleisten
    border1 = BorderFactory.createBevelBorder(BevelBorder.RAISED,Color.white,Color.white,new Color(134, 134, 134),new Color(93, 93, 93));
        // kein Titel in der Umrandung
    titledBorder1 = new TitledBorder("");

    jScrollBar1.setOrientation(JScrollBar.HORIZONTAL);
    jScrollBar1.setBorder(BorderFactory.createRaisedBevelBorder());
    jScrollBar1.setAutoscrolls(true);
    jScrollBar1.setBounds(new Rectangle(37, 17, 218, 20));
    jScrollBar1.addAdjustmentListener(new java.awt.event.AdjustmentListener() {
      public void adjustmentValueChanged(AdjustmentEvent e) {
        jScrollBar1_adjustmentValueChanged(e);
      }
    });

    txtValeurHS.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        txtValeurHS_actionPerformed(e);
      }
    });

    jScrollBar2.setBounds(new Rectangle(39, 51, 30, 27));
    jScrollBar2.addAdjustmentListener(new java.awt.event.AdjustmentListener() {
      public void adjustmentValueChanged(AdjustmentEvent e) {
        jScrollBar2_adjustmentValueChanged(e);
      }
    });
    jScrollBar2.setAutoscrolls(true);
    jScrollBar2.setUnitIncrement(-1);
    jScrollBar2.setBorder(BorderFactory.createRaisedBevelBorder());

    txtValeurVS.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        txtValeurVS_actionPerformed(e);
      }
    });

    ......
  }

   /**Ersetzt, damit wir das Fenster beim Schließen verlassen können*/
  protected void processWindowEvent(WindowEvent e) {
...
  }

  void jScrollBar1_adjustmentValueChanged(AdjustmentEvent e) {
    // Der Wert von Bildlaufleiste 1 hat sich geändert
    txtValeurHS.setText(""+jScrollBar1.getValue());
  }

  void jScrollBar2_adjustmentValueChanged(AdjustmentEvent e) {
    // Der Wert von Bildlaufleiste 2 hat sich geändert
    txtValeurVS.setText(""+jScrollBar2.getValue());
  }

  void txtValeurHS_actionPerformed(ActionEvent e) {
    // Der Wert der horizontalen Bildlaufleiste wird festgelegt
    setValeur(jScrollBar1,txtValeurHS);
  }

  void txtValeurVS_actionPerformed(ActionEvent e) {
    // Der Wert der vertikalen Bildlaufleiste wird festgelegt
    setValeur(jScrollBar2,txtValeurVS);
  }

  private void setValeur(JScrollBar jS, JTextField jT){
     // Der Wert der Bildlaufleiste jS wird mit dem Text aus dem Feld jT festgelegt
    int valeur=0;
    try{
      valeur=Integer.parseInt(jT.getText());
      jS.setValue(valeur);
    }
    catch (Exception e){
      // Der Fehler wird angezeigt
      afficher(""+e);
    }//try-catch
  }//setValeur

  void afficher(String message){
    // zeigt eine Meldung in einem Dialogfeld an
    JOptionPane.showMessageDialog(this,message,"Menus",JOptionPane.INFORMATION_MESSAGE);
  }//anzeigen

}

Hier ein Ausführungsbeispiel:

Image

5.2.5.6. Komponente JTextArea

Die Komponente JTextArea ist eine Komponente, in die mehrere Textzeilen eingegeben werden können, im Gegensatz zur Komponente JTextField, in die nur eine Zeile eingegeben werden kann. Wird diese Komponente in einen scrollbaren Container (JScrollPane) eingefügt, entsteht ein scrollbares Texteingabefeld. Diese Art von Komponente könnte beispielsweise in einer E-Mail-Anwendung vorkommen, in der der Text der zu versendenden Nachricht in eine Komponente JTextArea eingegeben wird. Die üblichen Methoden sind String getText(), um den Inhalt des Textfelds abzurufen, setText(String unTexte), um unTexte in das Textfeld einzufügen, sowie append(String unTexte), um unTexte an den bereits im Textfeld vorhandenen Text anzuhängen. Betrachten wir die folgende Anwendung:

Image

Nr.
Typ
Name
Rolle
1
JTextArea
txtTexte
ein mehrzeiliges Textfeld
2
JButton
cmdAfficher
zeigt den Inhalt von 1 in einem Dialogfeld an
3
JButton
cmdEffacer
löscht den Inhalt von 1
4
JTextField
txtAjout
Text, der dem Text von 1 hinzugefügt wird, wenn er mit der Eingabetaste bestätigt wird.
5
JScrollPane
jScrollPane1
Scrollbarer Container, in den Textfeld 1 eingefügt wurde, um ein scrollbares Textfeld zu erhalten.

Der entsprechende Code lautet wie folgt:

.....

public class cadreAppli extends JFrame {
  JPanel contentPane;
  JLabel jLabel1 = new JLabel();
  JButton cmdAfficher = new JButton();
  JScrollPane jScrollPane1 = new JScrollPane();
  JTextArea txtTexte = new JTextArea();
  JLabel jLabel2 = new JLabel();
  JTextField txtAjout = new JTextField();
  JButton cmdEffacer = new JButton();

  /**Rahmen erstellen*/
  public cadreAppli() {
    enableEvents(AWTEvent.WINDOW_EVENT_MASK);
    try {
      jbInit();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  }
   /**Komponente initialisieren*/
  private void jbInit() throws Exception  {

    cmdAfficher.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        cmdAfficher_actionPerformed(e);
      }
    });
    txtAjout.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        txtAjout_actionPerformed(e);
      }
    });
    cmdEffacer.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        cmdEffacer_actionPerformed(e);
      }
    });
    .......
    jScrollPane1.getViewport().add(txtTexte, null);
  }
   /**Ersetzt, damit wir das Programm beenden können, wenn das Fenster geschlossen wird*/
  protected void processWindowEvent(WindowEvent e) {
        ........
  }

  void cmdAfficher_actionPerformed(ActionEvent e) {
    // zeigt den Inhalt von TextArea an
    afficher(txtTexte.getText());
  }

    void afficher(String message){
     // zeigt eine Meldung in einem Dialogfeld an
    JOptionPane.showMessageDialog(this,message,"Suivi",JOptionPane.INFORMATION_MESSAGE);
  }// anzeigen

  void cmdEffacer_actionPerformed(ActionEvent e) {
    txtTexte.setText("");
  }//cmdEffacer_actionPerformed

  void txtAjout_actionPerformed(ActionEvent e) {
    // Text hinzufügen
    txtTexte.append(txtAjout.getText());
     // Leeren und Hinzufügen
    txtAjout.setText("");
  }//
}

5.2.6. Mausereignisse

Wenn man in einem Container zeichnet, ist es wichtig, die Position der Maus zu kennen, um beispielsweise bei einem Klick einen Punkt anzuzeigen. Mausbewegungen lösen Ereignisse in dem Container aus, in dem sich die Maus bewegt. Hier sind zum Beispiel die von JBuilder für einen Container JPanel angebotenen Ereignisse:

Image

mouseClicked
Mausklick
mouseDragged
Maus bewegt sich, linke Maustaste gedrückt
mouseEntered
Die Maus hat gerade den Bereich des Containers betreten
mouseExited
Die Maus hat gerade den Bereich des Containers verlassen
mouseMoved
Die Maus bewegt sich
mousePressed
Druck auf die linke Maustaste
mouseReleased
Loslassen der linken Maustaste

Hier ist ein Programm, mit dem Sie besser verstehen können, wann die verschiedenen Mausereignisse auftreten:

Image

Nr.
Typ
Name
Rolle
1
JTextField
txtPosition
um die Mausposition im Container anzuzeigen (ggf. MouseMoved)
2
JList
lstAffichage
um andere Mausereignisse als MouseMoved anzuzeigen
3
JButton
cmdEffacer
um den Inhalt von 2 zu löschen

Wenn man dieses Programm ausführt, erhält man bei einem Klick folgende Ausgabe:

Image

Die Ereignisse werden in der Liste von oben nach unten gestapelt. Der obige Screenshot zeigt also, dass ein Klick drei Ereignisse auslöst, und zwar in folgender Reihenfolge:

  1. MousePressed beim Drücken der Schaltfläche
  2. MouseReleased beim Loslassen
  3. MouseClicked, was bedeutet, dass die Abfolge der beiden vorherigen Ereignisse als Klick gewertet wird. Dies könnte ein Doppelklick sein. Die obige Information clickCount=1 zeigt jedoch an, dass es sich um einen einfachen Klick handelt.

Wenn man nun die Taste drückt, die Maus bewegt und die Taste loslässt:

Image

Hier sieht man die drei Ereignisse:

  1. MousePressed beim anfänglichen Drücken der Taste
  2. MouseDragged beim Bewegen der Maus bei gedrückter Taste
  3. MouseReleased beim Loslassen der Taste

In den beiden obigen Beispielen sieht man, dass ein Mausereignis verschiedene Informationen mit sich bringt, darunter die (x,y)-Koordinaten der Maus, zum Beispiel (408,65) in der ersten Zeile oben.

Fährt man so fort, stellt man fest, dass das Ereignis MouseExited ausgelöst wird, sobald die Maus den Container verlässt oder über eine seiner Komponenten fährt. Im letzteren Fall erhält der Container das Ereignis MouseExited und die Komponente das Ereignis MouseEntered. Das Gegenteil tritt ein, wenn die Maus die Komponente verlässt und wieder auf den Container zurückkehrt.

Was passiert bei einem Doppelklick?

Image

Es treten genau dieselben Ereignisse auf wie bei einem einfachen Klick. Lediglich enthält das Ereignis die Information clickCount=2 (siehe oben), die angibt, dass es sich tatsächlich um einen Doppelklick handelt.

Der relevante Code dieser Anwendung lautet wie folgt:

public class Cadre1 extends JFrame {
  JPanel contentPane;
  JLabel jLabel1 = new JLabel();
  JTextField txtPosition = new JTextField();
  JScrollPane jScrollPane1 = new JScrollPane();
  DefaultListModel valeurs=new DefaultListModel();
  JList lstAffichage = new JList(valeurs);
  JButton cmdEffacer = new JButton();

  /**Rahmen erstellen*/
  public Cadre1() {
    enableEvents(AWTEvent.WINDOW_EVENT_MASK);
    try {
      jbInit();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  }
   /**Komponente initialisieren*/
  private void jbInit() throws Exception  {

    contentPane.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
      public void mouseMoved(MouseEvent e) {
        contentPane_mouseMoved(e);
      }
      public void mouseDragged(MouseEvent e) {
        contentPane_mouseDragged(e);
      }
    });

    contentPane.addMouseListener(new java.awt.event.MouseAdapter() {
      public void mouseEntered(MouseEvent e) {
        contentPane_mouseEntered(e);
      }
      public void mouseExited(MouseEvent e) {
        contentPane_mouseExited(e);
      }
      public void mousePressed(MouseEvent e) {
        contentPane_mousePressed(e);
      }
      public void mouseClicked(MouseEvent e) {
        contentPane_mouseClicked(e);
      }
      public void mouseReleased(MouseEvent e) {
        contentPane_mouseReleased(e);
      }
    });

    cmdEffacer.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        cmdEffacer_actionPerformed(e);
      }
    });

    jScrollPane1.getViewport().add(lstAffichage, null);

...............
  }
   /**Ersetzt, damit wir das Programm beenden können, wenn das Fenster geschlossen wird*/
  protected void processWindowEvent(WindowEvent e) {
    .........
  }

  void contentPane_mouseMoved(MouseEvent e) {
    txtPosition.setText("("+e.getX()+","+e.getY()+")");
  }

  void contentPane_mouseDragged(MouseEvent e) {
    afficher(e);
  }

  void contentPane_mouseEntered(MouseEvent e) {
    afficher(e);
  }

  void afficher(MouseEvent e){
     // zeigt das Ereignis in der Liste an lstAffichage
    valeurs.insertElementAt(e,0);
  }

  void contentPane_mouseExited(MouseEvent e) {
    afficher(e);
  }

  void contentPane_mousePressed(MouseEvent e) {
    afficher(e);
  }

  void contentPane_mouseClicked(MouseEvent e) {
    afficher(e);
  }

  void contentPane_mouseReleased(MouseEvent e) {
    afficher(e);
  }

  void cmdEffacer_actionPerformed(ActionEvent e) {
     // löscht die Liste
    valeurs.removeAllElements();
  }
}

5.2.7. Ein Fenster mit Menü erstellen

Schauen wir uns nun an, wie man mit JBuilder ein Fenster mit Menü erstellt. Wir werden das folgende Fenster erstellen:

Image

Image

Erstellen Sie ein neues Projekt mit einem leeren Fenster als Ausgangspunkt. Wählen Sie aus der Liste der Komponenten unter „Swing-Container“ die Komponente JMenuBar (siehe Abbildung 1 unten) aus und ziehen Sie sie auf das zu entwerfende Fenster.

Image

Im Entwurfsfenster wird nichts angezeigt, aber die Komponente JMenuBar erscheint im Strukturbereich Ihres Fensters:

Image

Doppelklicken Sie auf das oben genannte Element jMenuBar1, um das Menü im Entwurfsmodus aufzurufen:

Image

1
Ein Menüelement einfügen
2
Trennzeichen einfügen
3
Ein verschachteltes Menü einfügen
4
Ein Menüelement löschen
5
Ein Menüelement deaktivieren
6
Menüpunkt zum Ankreuzen
7
Optionsfeld umkehren

Um Ihr erstes Menüelement zu erstellen, geben Sie „Optionen A“ in das Feld A oben ein und anschließend darunter in dieser Reihenfolge: A1, A2, Trennzeichen, A3, A4.

Image

Dann daneben:

Image

Verwenden Sie das Werkzeug 3, um anzugeben, dass B3 ein verschachteltes Untermenü ist.

Im Laufe der Menügestaltung verändert sich die logische Struktur unseres Fensters:

Image

Wenn wir unsere Anwendung nun ausführen, sehen wir ein leeres Fenster ohne Menü. Wir müssen das erstellte Menü unserem Fenster zuordnen. Wählen Sie dazu in der Fensterstruktur das Objekt this aus:

Image

Sie haben nun Zugriff auf die Eigenschaften von this:

Image

Eine davon ist „JMenuBar“, mit der das dem Fenster zugeordnete Menü festgelegt wird. Klicken Sie in die Zelle rechts neben „JMenuBar“. Daraufhin werden Ihnen alle erstellten Menüs zur Auswahl angezeigt. In diesem Fall steht nur jMenuBar1 zur Auswahl. Wählen Sie dieses aus.

Starten Sie die Anwendung (F9):

Image

Nun haben wir ein Menü, aber die Optionen haben vorerst noch keine Funktion. Die Menüoptionen werden wie Komponenten behandelt: Sie verfügen über Eigenschaften und Ereignisse. Wählen Sie in der Menüstruktur die Option jMenuItem1 aus:

Image

Sie haben nun Zugriff auf deren Eigenschaften und Ereignisse:

Image

Wählen Sie die Seite „Ereignisse“ aus und klicken Sie auf die Zelle rechts neben dem Ereignis „actionPerformed“: Dies ist das Ereignis, das ausgelöst wird, wenn auf ein Menüelement geklickt wird. Standardmäßig wird Ihnen eine Verarbeitungsprozedur vorgeschlagen. Doppelklicken Sie darauf, um Zugriff auf den Code zu erhalten:

Image

Wir schreiben den folgenden einfachen Code:

  void jMenuItem1_actionPerformed(ActionEvent e) {
    afficher("L'option A1 a été sélectionnée");
  }

  void afficher(String message){
     // zeigt eine Meldung in einem Dialogfeld an
    JOptionPane.showMessageDialog(this,message,"Menus",JOptionPane.INFORMATION_MESSAGE);
  }//anzeigen

Führen Sie die Anwendung aus und wählen Sie die Option A1 aus, um die folgende Meldung zu erhalten:

Image

Der relevante Code dieser Anwendung lautet wie folgt:

.....

public class Cadre1 extends JFrame {
  JPanel contentPane;
  BorderLayout borderLayout1 = new BorderLayout();
  JMenuBar jMenuBar1 = new JMenuBar();
  JMenu jMenu1 = new JMenu();
  JMenuItem jMenuItem1 = new JMenuItem();
  JMenuItem jMenuItem2 = new JMenuItem();
  JMenuItem jMenuItem3 = new JMenuItem();
  JMenuItem jMenuItem4 = new JMenuItem();
  JMenu jMenu2 = new JMenu();
  JMenuItem jMenuItem5 = new JMenuItem();
  JMenuItem jMenuItem6 = new JMenuItem();
  JMenu jMenu3 = new JMenu();
  JMenuItem jMenuItem7 = new JMenuItem();
  JMenuItem jMenuItem8 = new JMenuItem();
  JMenuItem jMenuItem9 = new JMenuItem();

  /**Rahmen erstellen*/
  public Cadre1() {
    enableEvents(AWTEvent.WINDOW_EVENT_MASK);
    try {
      jbInit();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  }
   /**Komponente initialisieren*/
  private void jbInit() throws Exception  {
        // Das Fenster ist mit einem Menü verknüpft
    this.setJMenuBar(jMenuBar1);

    jMenu1.setText("Options A");
    jMenuItem1.setText("A1");
    jMenuItem1.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        jMenuItem1_actionPerformed(e);
      }
    });
    jMenuItem2.setText("A2");
    jMenuItem3.setText("A3");
    jMenuItem4.setText("A4");
    jMenu2.setText("Options B");
    jMenuItem5.setText("B1");
    jMenuItem6.setText("B2");
    jMenu3.setText("B3");
    jMenuItem7.setText("B31");
    jMenuItem8.setText("B32");
    jMenuItem9.setText("B4");
    jMenuBar1.add(jMenu1);
    jMenuBar1.add(jMenu2);
    jMenu1.add(jMenuItem1);
    jMenu1.add(jMenuItem2);
    jMenu1.addSeparator();
    jMenu1.add(jMenuItem3);
    jMenu1.add(jMenuItem4);
    jMenu2.add(jMenuItem5);
    jMenu2.add(jMenuItem6);
    jMenu2.add(jMenu3);
    jMenu2.add(jMenuItem9);
    jMenu3.add(jMenuItem7);
    jMenu3.add(jMenuItem8);
  }
   /**Ersetzt, damit wir das Programm beenden können, wenn das Fenster geschlossen wird*/
  protected void processWindowEvent(WindowEvent e) {
....
  }

  void jMenuItem1_actionPerformed(ActionEvent e) {
    afficher("L'option A1 a été sélectionnée");
  }

  void afficher(String message){
     // Zeigt eine Meldung in einem Dialogfeld an
    JOptionPane.showMessageDialog(this,message,"Menus",JOptionPane.INFORMATION_MESSAGE);
  }//anzeigen

}

5.3. Dialogfelder

5.3.1. Meldungsfelder

Wir haben die Klasse JOptionPane bereits zur Anzeige von Meldungen verwendet. So sieht der folgende Code aus:

import javax.swing.*;

public class dialog1 {
  public static void main(String arg[]){
    JOptionPane.showMessageDialog(null,"Un message","Titre de la boîte",JOptionPane.INFORMATION_MESSAGE);
  }
}

erzeugt die Anzeige des folgenden Feldes:

Image

Wenn man dieses Fenster schließt, verschwindet es, aber der Ausführungs-Thread, in dem es lief, wird nicht beendet. Dieses Phänomen tritt normalerweise nicht auf. Die Dialogfelder werden innerhalb einer Anwendung verwendet, die zu einem bestimmten Zeitpunkt die Anweisung System.exit(n) verwendet, um alle Threads zu beenden. Daran werden wir uns in den folgenden Beispielen erinnern, die alle nach dem gleichen Muster aufgebaut sind. Unter DOS kann die Anwendung mit Strg-C unterbrochen werden. Bei JBuilder verwenden wir die Option „Programm ausführen/zurücksetzen“ (Strg-F2). Übrigens ist das erste Argument von showMessageDialog hier null. Im Allgemeinen ist dies jedoch nicht der Fall. Meistens ist es this, wobei this das Hauptfenster der Anwendung bezeichnet.

5.3.2. Darstellung und Handhabung

Das Erscheinungsbild des obigen Fensters könnte anders aussehen. Dieses Erscheinungsbild lässt sich über die Klasse javax.swing.UIManager konfigurieren. Als wir den von JBuilder für unser erstes Fenster generierten Code kommentiert haben, sind wir auf eine Anweisung gestoßen, auf die wir nicht näher eingegangen sind:

      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

Die Methode setLookAndFeel der Klasse UIManager (UI = Benutzeroberfläche) ermöglicht es, das Erscheinungsbild der grafischen Benutzeroberflächen festzulegen. Die Klasse UIManager verfügt über eine Methode, mit der sich die möglichen „Darstellungsformen“ für die Benutzeroberflächen ermitteln lassen:

static UIManager.LookAndFeelInfo[]
getInstalledLookAndFeels()

Die Methode gibt ein Array von Elementen des Typs LookAndFeelInfo zurück. Diese Klasse verfügt über eine Methode:

String
getClassName()

die den Namen der Klasse zurückgibt, die ein bestimmtes Erscheinungsbild „implementiert“. Probieren wir das folgende Programm aus:

import javax.swing.*;

public class LookAndFeels {
  // zeigt die verfügbaren Look-and-Feels an
  public static void main(String[] args) {
    // Listet die installierten Look-and-Feels auf
    UIManager.LookAndFeelInfo[] lf=UIManager.getInstalledLookAndFeels();
    // Anzeige
    for(int i=0;i<lf.length;i++){
      System.out.println(lf[i].getClassName());
    }//für
  }//Hauptmenü
}//sortiert

Dies liefert folgende Ergebnisse:

javax.swing.plaf.metal.MetalLookAndFeel
com.sun.java.swing.plaf.motif.MotifLookAndFeel
com.sun.java.swing.plaf.windows.WindowsLookAndFeel

Es scheint also drei verschiedene „Darstellungsvarianten“ zu geben. Kehren wir zu unserem Programm zur Anzeige von Meldungen zurück und probieren wir die verschiedenen möglichen Darstellungsvarianten aus:

import javax.swing.*;

public class LookAndFeel2 {
  // zeigt die verfügbaren Look-and-Feels an
  public static void main(String[] args) {
    // Liste der installierten Look-and-Feels
    UIManager.LookAndFeelInfo[] lf=UIManager.getInstalledLookAndFeels();
    // Anzeige
    for(int i=0;i<lf.length;i++){
      // Look-and-Feel-Manager
      try{
        UIManager.setLookAndFeel(lf[i].getClassName());
      }catch(Exception ex){
        System.err.println(ex.getMessage());
      }//Catch
      // Meldung
      JOptionPane.showMessageDialog(null,"Un message",lf[i].getClassName(),JOptionPane.INFORMATION_MESSAGE);
    }//for
  }//main
}//Klasse

Die Ausführung liefert folgende Ausgaben:

die von rechts nach links den „Looks“ Metal, Motif und Windows entsprechen.

5.3.3. Bestätigungsdialoge

Die Klasse JOptionPane verfügt über eine Methode showConfirmDialog zum Anzeigen von Bestätigungsdialogen mit den Schaltflächen Oui, Non, Annuler. Es gibt mehrere überladene Methoden showConfirmDialog. Wir betrachten eine davon:

static int
showConfirmDialog(Component parentComponent, Object message, String title, int optionType)
parentComponent
die übergeordnete Komponente des Dialogfelds. Oft das Fenster oder der Wert null
message
Die anzuzeigende Meldung
title
der Titel des Dialogfelds
optionType
JOptionPane.YES_NO_OPTION: Schaltflächen „Ja“, „Nein“
JOptionPane.YES_NO_CANCEL_OPTION: Schaltflächen „Ja“, „Nein“, „Abbrechen“

Das von der Methode zurückgegebene Ergebnis lautet:

JOptionPane.YES_OPTION
Der Benutzer hat auf „Ja“ geklickt
JOptionPane.NO_OPTION
Der Benutzer hat auf „Nein“ geklickt
JOptionPane.CANCEL_OPTION
Der Benutzer hat auf „Abbrechen“ geklickt
JOptionPane.CLOSED_OPTION
Der Benutzer hat das Fenster geschlossen

Hier ein Beispiel:

import javax.swing.*;

public class confirm1 {
  public static void main(String[] args) {
    // zeigt Bestätigungsfelder an
    int réponse;
    affiche(JOptionPane.showConfirmDialog(null,"Voulez-vous continuer ?","Confirmation",JOptionPane.YES_NO_OPTION));
    affiche(JOptionPane.showConfirmDialog(null,"Voulez-vous continuer ?","Confirmation",JOptionPane.YES_NO_CANCEL_OPTION));
  }//Hauptprogramm

  private static void affiche(int réponse){
     // gibt an, welche Art von Antwort man erhalten hat
    switch(réponse){
      case JOptionPane.YES_OPTION :
        System.out.println("Oui");
        break;
      case JOptionPane.NO_OPTION :
        System.out.println("Non");
        break;
      case JOptionPane.CANCEL_OPTION :
        System.out.println("Annuler");
        break;
      case JOptionPane.CLOSED_OPTION :
        System.out.println("Fermeture");
        break;
    }//-Schalter
  }//-Display
}//klassifizieren

Auf der Konsole werden die Meldungen Non und Annuler angezeigt.

5.3.4. Eingabefeld

Die Klasse JOptionPane bietet zudem die Möglichkeit, eine Eingabe mit der Methode showInputDialog vorzunehmen. Auch hier gibt es mehrere überladene Methoden. Wir stellen eine davon vor:

static String
showInputDialog(Component parentComponent, Object message, String title, int messageType)

Die Argumente sind die bereits mehrfach erwähnten. Die Methode gibt die vom Benutzer eingegebene Zeichenkette zurück. Hier ein Beispiel:

import javax.swing.*;

public class input1 {
  public static void main(String[] args) {
    // Eingabe
    System.out.println("Chaîne saisie ["+
      JOptionPane.showInputDialog(null,"Quel est votre nom","Saisie du nom",JOptionPane.QUESTION_MESSAGE )
      + "]");
  }//Hand
}//Klasse

Die Darstellung des Eingabefelds:

Image

Die Konsolenanzeige:

Chaîne saisie [dupont]

5.4. Auswahlfelder

Wir befassen uns nun mit einer Reihe von vordefinierten Auswahllisten in Java 2:

JFileChooser
Auswahlfeld zum Auswählen einer Datei in der Dateistruktur
JColorChooser
Auswahlfeld zur Auswahl einer Farbe

5.4.1. Auswahlfeld JFileChooser

Wir werden die folgende Anwendung erstellen:

Image

Die Steuerelemente sind folgende:

Nr.
Typ
Name
Rolle
0
JScrollPane
jScrollPane1
Scrollbarer Container für Textfeld 1
1
JTextArea selbst im JScrollPane
txtTexte
vom Benutzer eingegebener oder aus einer Datei geladener Text
2
JButton
btnSauvegarder
ermöglicht das Speichern des Textes aus 1 in einer Textdatei
3
JButton
btnCharger
ermöglicht das Einlesen des Inhalts einer Textdatei in 1
4
JButton
btnEffacer
löscht den Inhalt von 1

Es wird ein nicht-visuelles Steuerelement verwendet: jFileChooser1. Dieses wird aus der Swing-Container-Palette von JBuilder entnommen:

Image

Wir platzieren die Komponente im Entwurfsfenster, jedoch außerhalb des Formulars. Sie erscheint in der Komponentenliste:

Image

Wir geben nun den relevanten Programmcode an, um einen Überblick zu erhalten:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import java.io.*;

public class dialogues extends JFrame {
   // die Rahmenkomponenten
  JPanel contentPane;
  JButton btnSauvegarder = new JButton();
  JButton btnCharger = new JButton();
  JButton btnEffacer = new JButton();
  JScrollPane jScrollPane1 = new JScrollPane();
  JTextArea txtTexte = new JTextArea();
  JFileChooser jFileChooser1 = new JFileChooser();

  // Dateifilter
  javax.swing.filechooser.FileFilter filtreTxt = null;

   //Rahmen erstellen
  public dialogues() {
    enableEvents(AWTEvent.WINDOW_EVENT_MASK);
    try {
      jbInit();
       // weitere Initialisierungen
      moreInit();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  }

   // moreInit
  private void moreInit(){
     // Initialisierungen beim Erstellen des Fensters
     // Filter *.txt
    filtreTxt = new javax.swing.filechooser.FileFilter(){
      public boolean accept(File f){
        // Wird „f“ akzeptiert?
        return f.getName().toLowerCase().endsWith(".txt");
      }//akzeptiert
      public String getDescription(){
        // Beschreibung des Filters
        return "Fichiers Texte (*.txt)";
      }//getDescription
    };
     // Der Filter wird hinzugefügt
    jFileChooser1.addChoosableFileFilter(filtreTxt);
    // man möchte außerdem den Filter für alle Dateien
    jFileChooser1.setAcceptAllFileFilterUsed(true);
    // Das Startverzeichnis der Box FileChooser wird auf das aktuelle Verzeichnis festgelegt
    jFileChooser1.setCurrentDirectory(new File("."));
  }

   //Die Komponente initialisieren
  private void jbInit() throws Exception  {
.......................
  }
   //Ersetzt, damit wir das Programm beenden können, wenn das Fenster geschlossen wird
  protected void processWindowEvent(WindowEvent e) {
......................
    }
  }

  void btnCharger_actionPerformed(ActionEvent e) {
    // Auswahl einer Datei mithilfe eines Objekts JFileChooser

     // Der anfängliche Filter wird festgelegt
    jFileChooser1.setFileFilter(filtreTxt);
     // Das Auswahlfeld wird angezeigt
    int returnVal = jFileChooser1.showOpenDialog(this);
    // Hat der Benutzer etwas ausgewählt?
    if(returnVal == JFileChooser.APPROVE_OPTION) {
      // Die Datei wird in das Textfeld eingefügt
       lireFichier(jFileChooser1.getSelectedFile());
    }//if
  }//btnCharger_actionPerformed

  // lireFichier
  private void lireFichier(File fichier){
     // zeigt den Inhalt der Textdatei „fichier“ im Textfeld an

     // Das Textfeld wird gelöscht
    txtTexte.setText("");

     // einige Daten
    BufferedReader IN=null;
    String ligne=null;
    try{
      // Datei zum Lesen öffnen
      IN=new BufferedReader(new FileReader(fichier));
      // Die Datei wird zeilenweise gelesen
      while((ligne=IN.readLine())!=null){
        txtTexte.append(ligne+"\n");
      }//while
       // Datei schließen
      IN.close();
    }catch(Exception ex){
       // Es ist ein Fehler aufgetreten
      txtTexte.setText(""+ex);
    }//catch
  }

  // Löschen
  void btnEffacer_actionPerformed(ActionEvent e) {
    // Textfeld wird gelöscht
    txtTexte.setText("");
  }

   // speichern
  void btnSauvegarder_actionPerformed(ActionEvent e) {
     // speichert den Inhalt des Textfelds in einer Datei

     // Der anfängliche Filter wird festgelegt
    jFileChooser1.setFileFilter(filtreTxt);
     // Das Auswahlfeld zum Speichern wird angezeigt
    int returnVal = jFileChooser1.showSaveDialog(this);
    // Hat der Benutzer etwas ausgewählt?
    if(returnVal == JFileChooser.APPROVE_OPTION) {
      // Der Inhalt des Textfelds wird in eine Datei geschrieben
       écrireFichier(jFileChooser1.getSelectedFile());
    }//if
  }

   // lireFichier
  private void écrireFichier(File fichier){
     // schreibt den Inhalt des Textfelds in eine Datei

     // einige Daten
    PrintWriter PRN=null;
    try{
       // Datei zum Schreiben öffnen
      PRN=new PrintWriter(new FileWriter(fichier));
      // Der Inhalt des Textfelds wird geschrieben
      PRN.print(txtTexte.getText());
       // Datei schließen
      PRN.close();
    }catch(Exception ex){
       // Es ist ein Fehler aufgetreten
      txtTexte.setText(""+ex);
    }//Abfangen
  }

Wir werden den Code der Methoden btnEffacer_Click, lireFichier und écrireFichier nicht näher erläutern, da sie nichts Neues enthalten, was nicht bereits behandelt wurde. Wir werden uns mit der Klasse JFileChooser und ihrer Verwendung näher befassen. Diese Klasse ist komplex, fast schon „unübersichtlich“. Wir verwenden hier nur die folgenden Methoden:

addChoosableFilter(FileFilter)
legt die zur Auswahl angebotenen Dateitypen fest
setAcceptAllFileFilterUsed(boolean)
gibt an, ob der Typ „Alle Dateien“ zur Auswahl angeboten werden soll oder nicht
File getSelectedFile()
die vom Benutzer ausgewählte Datei (File)
int showSaveDialog()
Methode, die das Auswahlfeld zum Speichern anzeigt. Gibt ein Ergebnis vom Typ int zurück. Der Wert jFileChooser.APPROVE_OPTION zeigt an, dass der Benutzer eine gültige Auswahl getroffen hat. Andernfalls hat er entweder die Auswahl abgebrochen oder es ist ein Fehler aufgetreten.
setCurrentDirectory
um das Startverzeichnis festzulegen, von dem aus der Benutzer mit der Erkundung des Dateisystems beginnt
setFileFilter(FileFilter)
um den aktiven Filter festzulegen

Die Methode showSaveDialog zeigt ein Auswahlfeld an, das in etwa wie folgt aussieht:

Image

1
Dropdown-Liste, die mit der Methode addChoosableFilter erstellt wurde. Sie enthält sogenannte Auswahlfilter, die durch die Klasse FileFilter repräsentiert werden. Es ist Aufgabe des Entwicklers, diese Filter zu definieren und zur Liste 1 hinzuzufügen.
2
Aktuelles Verzeichnis, festgelegt durch die Methode setCurrentDirectory, sofern diese Methode verwendet wurde; andernfalls ist das aktuelle Verzeichnis unter Windows der Ordner „Eigene Dateien“ oder unter Unix das Home-Verzeichnis.
3
Name der ausgewählten oder vom Benutzer direkt eingegebenen Datei. Wird mit der Methode getSelectedFile() bereitgestellt
4
Schaltflächen „Speichern“/„Abbrechen“. Wenn die Schaltfläche Enregistrer verwendet wird, liefert die Methode showSaveDialog das Ergebnis jFileChooser.APPROVE_OPTION

Wie werden die Dateifilter der Dropdown-Liste 1 erstellt? Die Filter werden mithilfe der folgenden Methode zur Liste 1 hinzugefügt:

addChoosableFilter(FileFilter)
legt die zur Auswahl angebotenen Dateitypen fest

der Klasse JFileChooser. Nun müssen wir noch die Klasse FileFilter kennenlernen. Dabei handelt es sich eigentlich um die Klasse javax.swing.filechooser.FileFilter, die eine abstrakte Klasse ist, c.a.d – eine Klasse, die nicht instanziiert, sondern nur abgeleitet werden kann. Sie ist wie folgt definiert:

FileFilter()
Konstruktor
boolean accept(File)
Gibt an, ob die Datei f zum Filter gehört oder nicht
String getDescription()
Beschreibungszeichenfolge des Filters

Nehmen wir ein Beispiel. Wir möchten, dass die Dropdown-Liste 1 einen Filter zur Auswahl der Dateien *.txt mit der Beschreibung „Textdateien (*.txt)“ anbietet.

  • Dazu müssen wir eine Klasse erstellen, die von der Klasse FileFilter abgeleitet ist
  • die Methode `boolean accept(File f)` verwenden, um den Wert `true` zurückzugeben, wenn der Dateiname `f` auf `.txt` endet
  • die Methode String getDescription() verwenden, um die Beschreibung „Textdateien (*.txt)“ zurückzugeben

Dieser Filter könnte in unserer Anwendung wie folgt definiert werden:

  javax.swing.filechooser.FileFilter filtreTxt = new javax.swing.filechooser.FileFilter(){
    public boolean accept(File f){
      // Wird „f“ akzeptiert?
      return f.getName().toLowerCase().endsWith(".txt");
    }//akzeptiert
    public String getDescription(){
      // Filterbeschreibung
      return "Fichiers Texte (*.txt)";
    }//getDescription
  };

Dieser Filter würde durch die folgende Anweisung zur Filterliste des Objekts jFileChooser1 hinzugefügt:

     // Der Filter *.txt wird hinzugefügt
    jFileChooser1.addChoosableFileFilter(filtretxt);

All dies und einige weitere Initialisierungen werden in der Methode moreInit durchgeführt, die beim Erstellen des Fensters ausgeführt wird (siehe vollständiges Programm oben). Der Code der Schaltfläche Sauvegarder lautet wie folgt:

  void btnSauvegarder_actionPerformed(ActionEvent e) {
    // speichert den Inhalt des Textfelds in einer Datei

     // Der anfängliche Filter wird festgelegt
    jFileChooser1.setFileFilter(filtreTxt);
     // Das Auswahlfeld zum Speichern wird angezeigt
    int returnVal = jFileChooser1.showSaveDialog(this);
    // Hat der Benutzer eine Auswahl getroffen?
    if(returnVal == JFileChooser.APPROVE_OPTION) {
      // Der Inhalt des Textfelds wird in eine Datei geschrieben
       écrireFichier(jFileChooser1.getSelectedFile());
    }//if
  }

Die Abfolge der Schritte ist wie folgt:

  • Der aktive Filter wird auf den Filter *.txt festgelegt, damit der Benutzer vorrangig nach diesem Dateityp suchen kann. Der Filter „Alle Dateien“ ist ebenfalls vorhanden. Er wurde in der Prozedur moreInit hinzugefügt. Es stehen also zwei Filter zur Verfügung.
  • Das Auswahlfeld zum Speichern wird angezeigt. An dieser Stelle haben wir keine Kontrolle mehr, da der Benutzer das Auswahlfeld nutzt, um eine Datei aus dem Dateisystem auszuwählen.
  • Wenn er das Auswahlfeld verlässt, wird der Rückgabewert geprüft, um festzustellen, ob das Textfeld gespeichert werden soll oder nicht. Falls ja, muss es in der Datei gespeichert werden, die über die Methode getSelectedFile abgerufen wird.

Der Code für die Schaltfläche „Laden“ ist dem Code für die Schaltfläche „Speichern“ sehr ähnlich.

  void btnCharger_actionPerformed(ActionEvent e) {
    // Auswahl einer Datei mithilfe eines Objekts JFileChooser

     // Der anfängliche Filter wird festgelegt
    jFileChooser1.setFileFilter(filtreTxt);
     // Anzeige des Auswahlfelds
    int returnVal = jFileChooser1.showOpenDialog(this);
    // Hat der Benutzer etwas ausgewählt?
    if(returnVal == JFileChooser.APPROVE_OPTION) {
      // Die Datei wird in das Textfeld eingefügt
       lireFichier(jFileChooser1.getSelectedFile());
    }//if
  }//btnCharger_actionPerformed

Es gibt zwei Unterschiede:

  • Um das Dateiauswahlfeld anzuzeigen, wird die Methode showOpenDialog anstelle der Methode showSaveDialog verwendet. Das angezeigte Auswahlfeld entspricht demjenigen, das von der Methode showSaveDialog angezeigt wird.
  • Wenn der Benutzer eine Datei ausgewählt hat, wird die Methode lireFichier anstelle der Methode écrireFichier aufgerufen.

5.4.1.1. Auswahldialoge JColorChooser und JFontChooser

Wir setzen das vorherige Beispiel fort und fügen zwei neue Schaltflächen hinzu:

Image

Nr.
Typ
Name
Rolle
6
JButton
btnCouleur
um die Schriftfarbe von TextBox festzulegen
7
JButton
btnPolice
zum Festlegen der Schriftart für TextBox

Die Komponente JColorChooser, mit der ein Farbauswahlfeld angezeigt werden kann, ist in der Liste der Swing-Komponenten von JBuilder zu finden:

Image

Wir fügen diese Komponente in das Entwurfsfenster ein, jedoch außerhalb des Formulars. Sie ist im Formular nicht sichtbar, aber dennoch in der Komponentenliste des Fensters vorhanden:

Image

Die Klasse JColorChooser ist sehr einfach aufgebaut. Das Farbauswahlfeld wird mit der Methode int showDialog angezeigt:

static Color
showDialog(Component component, String title, Color initialColor)
Component component
die übergeordnete Komponente des Farbauswahlfelds, in der Regel ein Fenster JFrame
String title
der Titel in der Titelleiste des Auswahlfelds
Farbe intialColor
ursprünglich im Auswahlfeld ausgewählte Farbe

Wenn der Benutzer eine Farbe auswählt, gibt die Methode eine Farbe zurück, andernfalls den Wert null. Der mit der Schaltfläche verknüpfte Code Couleur lautet wie folgt:

  void btnCouleur_actionPerformed(ActionEvent e) {
     // Auswahl einer Textfarbe mithilfe der Komponente JColorChooser
    Color couleur;
    if((couleur=jColorChooser1.showDialog(this,"Choix d'une couleur",Color.BLACK))!=null){
       // Festlegen der Schriftfarbe im Textfeld
      txtTexte.setForeground(couleur);
    }//if
  }

Die Klasse Color ist in java.awt.Color definiert. Dort sind verschiedene Konstanten definiert, darunter Color.BLACK für die Farbe Schwarz. Das angezeigte Auswahlfeld sieht wie folgt aus

Image

Seltsamerweise bietet die Swing-Bibliothek keine Klasse zur Auswahl einer Schriftart an. Glücklicherweise gibt es die Java-Ressourcen im Internet. Bei einer Suche nach dem Stichwort „JFontChooser“, das ein möglicher Name für eine solche Klasse zu sein scheint, findet man mehrere Treffer. Das folgende Beispiel gibt uns die Gelegenheit, JBuilder so zu konfigurieren, dass es Pakete verwendet, die in der ursprünglichen Konfiguration nicht vorgesehen waren.

Das heruntergeladene Paket heißt swingextras.jar und wurde im Ordner <jdk>\jre\lib\perso abgelegt, wobei <jdk> das Installationsverzeichnis des von JBuilder verwendeten JDK bezeichnet. Es hätte auch an einer beliebigen anderen Stelle abgelegt werden können.

Sehen wir uns den Inhalt des Pakets SwingExtras.jar an:

Image

Darin befindet sich der Java-Quellcode der im Paket enthaltenen Komponenten. Außerdem sind dort die Klassen selbst enthalten:

Image

Aus diesem Archiv geht hervor, dass die Klasse JFontChooser eigentlich com.lamatek.swingextras.JFontChooser heißt. Wenn wir den vollständigen Namen nicht schreiben möchten, müssen wir am Anfang des Programms Folgendes schreiben:

import com.lamatek.swingextras.*;

Wie finden der Compiler und die Java-Virtual-Machine dieses neue Paket? Im Falle einer direkten Verwendung von JDK wurde dies bereits erläutert; der Leser findet die Erläuterungen im Abschnitt über Java-Pakete. Hier gehen wir näher auf die Vorgehensweise bei der Verwendung von JBuilder ein. Die Pakete werden im Menü „Optionen/JDK konfigurieren“ eingerichtet:

Image

1
Über die Schaltfläche „Modifier“ (1) kann man JBuilder mitteilen, welches JDK verwendet werden soll. In diesem Beispiel hatte JBuilder die Version 1.3.1 von JDK mitgebracht. Als JDK 1.4 veröffentlicht wurde, wurde es separat von JBuilder installiert, und man nutzte die Schaltfläche Modifier, um JBuilder anzuweisen,künftig JDK 1.4 zu verwenden, indem das Installationsverzeichnis des letzteren angegeben wurde
2
Stammverzeichnis von JDK, das derzeit von JBuilder verwendet wird
3
Liste der von JBuilder verwendeten Java-Archive (.jar). Über die Schaltfläche Ajouter (4) können weitere hinzugefügt werden
4
Über die Schaltfläche Ajouter (4) können neue Pakete hinzugefügt werden, die JBuilder sowohl für die Kompilierung als auch für die Ausführung von Programmen verwendet. Hier wurde sie verwendet, um das Paket SwingExtras.jar (5) hinzuzufügen

Nun ist JBuilder korrekt konfiguriert, um die Klasse JFontChooser nutzen zu können. Allerdings bräuchten wir Zugriff auf die Definition dieser Klasse, um sie korrekt verwenden zu können. Das Archiv swingextras.jar enthält HTML-Dateien, die wir extrahieren könnten, um sie zu nutzen. Das ist jedoch nicht notwendig. Die in den .jar-Dateien enthaltene Java-Dokumentation ist direkt über JBuilder zugänglich. Dazu muss die Registerkarte Documentation (6) oben konfiguriert werden. Es erscheint das folgende neue Fenster:

Image

Über die Schaltfläche Ajouter können wir festlegen, dass die Datei SwingExtras.jar nach Dokumentation durchsucht werden soll. Nach Bestätigung dieses Vorgangs lässt sich feststellen, dass wir tatsächlich Zugriff auf die Dokumentation von SwingExtras.jar haben. Dies bringt verschiedene Vorteile mit sich:

  • Wenn man mit der Eingabe des Importbefehls beginnt
import com.lamatek.swingextras.*;

wird man feststellen, dass JBuilder eine Hilfe bereitstellt:

Image

Das Paket com.lamatek wurde erfolgreich gefunden.

  • Wenn wir nun zum folgenden Programm übergehen:
import com.lamatek.swingextras.*;

public class test{
  JFontChooser jFontChooser1=null;
}  

Wenn man F1 auf das Schlüsselwort JFontChooser anwendet, erhält man eine Hilfe zu dieser Klasse:

Image

In der Statusleiste 1 ist zu sehen, dass tatsächlich eine HTML-Datei aus dem Paket swingextras.jar verwendet wird. Das oben gezeigte Beispiel ist aussagekräftig genug, um den Code für die Schaltfläche Police unserer Anwendung zu schreiben:

  void btnPolice_actionPerformed(ActionEvent e) {
    // Auswahl einer Schriftart mithilfe der Komponente JFontChooser
    jFontChooser1 = new JFontChooser(new Font("Arial", Font.BOLD, 12));
    if (jFontChooser1.showDialog(this, "Choix d'une police") == JFontChooser.ACCEPT_OPTION) {
      // Ändern der Schriftart der Zeichen im Textfeld
      txtTexte.setFont(jFontChooser1.getSelectedFont());
    }//if
  }

Das von der oben genannten Methode showDialog angezeigte Auswahlfeld sieht wie folgt aus:

Image

5.5. Die grafische Anwendung IMPOTS

Wir greifen auf die Anwendung IMPOTS zurück, die bereits zweimal behandelt wurde. Nun fügen wir ihr eine grafische Benutzeroberfläche hinzu:

Image

Die Steuerelemente sind wie folgt

Nr.
Typ
Name
Rolle
1
JRadioButton
rdOui
ankreuzen, wenn verheiratet
2
JRadioButton
rdNon
ankreuzen, wenn unverheiratet
3
JSpinner
spinEnfants
Anzahl der Kinder des Steuerpflichtigen
Minimum=0, Maximum=20, Schrittweite=1
4
JTextField
txtSalaire
Jahresgehalt des Steuerpflichtigen in F
5
JLabel
lblImpots
Höhe der zu zahlenden Steuer
6
JTextField
txtStatus
Feld für Statusmeldungen – nicht änderbar

Das Menü sieht wie folgt aus:

Hauptoption
Unteroption
Name
Rolle
Steuern
   
 
Initialisieren
mnuInitialiser
Lädt die für die Berechnung erforderlichen Daten aus einer Textdatei
 
Berechnen
mnuCalculer
berechnet die zu zahlende Steuer, sobald alle erforderlichen Daten vorliegen und korrekt sind
 
Löschen
mnuEffacer
Setzt das Formular in seinen Ausgangszustand zurück
 
Beenden
mnuQuitter
beendet die Anwendung

Funktionsregeln

  • Das Menü Calculer bleibt ausgeblendet, solange das Gehaltsfeld leer ist
  • Wenn sich bei Start der Berechnung herausstellt, dass das Gehalt falsch ist, wird der Fehler gemeldet:

Image

Das Programm ist unten aufgeführt. Es verwendet die Klasse impots, die im Kapitel über Klassen erstellt wurde. Ein Teil des Codes, der automatisch von JBuilder generiert wird, wurde hier nicht wiedergegeben.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import java.io.*;
import java.util.*;
import javax.swing.event.*;

public class frmImpots extends JFrame {
  // die Komponenten des Fensters
  JPanel contentPane;
  JMenuBar jMenuBar1 = new JMenuBar();
  JMenu jMenu1 = new JMenu();
  JMenuItem mnuInitialiser = new JMenuItem();
  JMenuItem mnuCalculer = new JMenuItem();
  JMenuItem mnuEffacer = new JMenuItem();
  JMenuItem mnuQuitter = new JMenuItem();
  JLabel jLabel1 = new JLabel();
  JFileChooser jFileChooser1 = new JFileChooser();
  JTextField txtStatus = new JTextField();
  JRadioButton rdOui = new JRadioButton();
  JRadioButton rdNon = new JRadioButton();
  JLabel jLabel2 = new JLabel();
  JLabel jLabel3 = new JLabel();
  JTextField txtSalaire = new JTextField();
  JLabel jLabel4 = new JLabel();
  JLabel jLabel5 = new JLabel();
  JLabel lblImpots = new JLabel();
  JLabel jLabel7 = new JLabel();
  ButtonGroup buttonGroup1 = new ButtonGroup();
  JSpinner spinEnfants=null;
  FileFilter filtreTxt=null;

   // die Attribute der Klasse
  double[] limites=null;
  double[] coeffr=null;
  double[] coeffn=null;
  impots objImpots=null;

   //Den Rahmen erstellen
  public frmImpots() {
    enableEvents(AWTEvent.WINDOW_EVENT_MASK);
    try {
      jbInit();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
     // weitere Initialisierungen
    moreInit();
  }

   // Formularinitialisierung
  private void moreInit(){
     // Menü „Berechnen“ gesperrt
    mnuCalculer.setEnabled(false);
    // Eingabefelder gesperrt
    txtSalaire.setEditable(false);
    txtSalaire.setBackground(Color.WHITE);
    // Statusfeld
    txtStatus.setBackground(Color.WHITE);
    // Spinner „Kinder“ – zwischen 0 und 20 Kindern
    spinEnfants=new JSpinner(new SpinnerNumberModel(0,0,20,1));
    spinEnfants.setBounds(new Rectangle(137,60,40,27));
    contentPane.add(spinEnfants);
     // Filter *.txt für das Auswahlfeld
    filtreTxt = new javax.swing.filechooser.FileFilter(){
      public boolean accept(File f){
        // Wird „f“ akzeptiert?
        return f.getName().toLowerCase().endsWith(".txt");
      }//akzeptiert
      public String getDescription(){
        // Filterbeschreibung
        return "Fichiers Texte (*.txt)";
      }//getDescription
    };
     // Der Filter *.txt wird hinzugefügt
    jFileChooser1.addChoosableFileFilter(filtreTxt);
    // man möchte außerdem den Filter für alle Dateien
    jFileChooser1.setAcceptAllFileFilterUsed(true);
    // Das Startverzeichnis der Box wird festgelegt FileChooser
    jFileChooser1.setCurrentDirectory(new File("."));
  }//moreInit

   //Die Komponente initialisieren
  private void jbInit() throws Exception  {

................

  }

   //Ersetzt, damit wir die Anwendung beenden können, wenn das Fenster geschlossen wird
  protected void processWindowEvent(WindowEvent e) {
.....................
  }

  void mnuQuitter_actionPerformed(ActionEvent e) {
    // Die Anwendung wird beendet
    System.exit(0);
  }

  void mnuInitialiser_actionPerformed(ActionEvent e) {
    // Die Datendatei wird geladen
     // die über das Auswahlfeld ausgewählt wird JFileChooser1
    jFileChooser1.setFileFilter(filtreTxt);
    if (jFileChooser1.showOpenDialog(this)!=JFileChooser.APPROVE_OPTION)
      return;
     // Die ausgewählte Datei wird verarbeitet
    try{
       // Daten einlesen
      lireFichier(jFileChooser1.getSelectedFile());
       // Erstellung des Steuerobjekts
      objImpots=new impots(limites,coeffr,coeffn);
       // Bestätigung
      txtStatus.setText("Données chargées");
       // Das Gehalt kann geändert werden
      txtSalaire.setEditable(true);
       // Keine weiteren Änderungen möglich
      mnuInitialiser.setEnabled(false);
    }catch(Exception ex){
       // Problem
      txtStatus.setText("Erreur : " + ex.getMessage());
      // Ende
      return;
    }//Abfangen
  }

  private void lireFichier(File fichier) throws Exception {
     // die Datentabellen
    ArrayList aLimites=new ArrayList();
    ArrayList aCoeffR=new ArrayList();
    ArrayList aCoeffN=new ArrayList();
    String[] champs=null;

     // Datei zum Lesen öffnen
    BufferedReader IN=new BufferedReader(new FileReader(fichier));
    // Die Datei wird zeilenweise gelesen
     // sie haben die Form „Grenzwert, Koeffizient, Koeffizient“
    String ligne=null;
    int numLigne=0;           // aktuelle Zeilennummer
    while((ligne=IN.readLine())!=null){
      // eine weitere Zeile
      numLigne++;
       // Die Zeile wird in Felder zerlegt
      champs=ligne.split("\\s+");
       // 3 Felder?
      if(champs.length!=3)
        throw new Exception("ligne " + numLigne + "erronée dans fichier des données");
       // die drei Felder werden abgerufen
       aLimites.add(champs[0]);
       aCoeffR.add(champs[1]);
       aCoeffN.add(champs[2]);
    }//while
     // Datei schließen
    IN.close();
     // Übertragung der Daten in begrenzte Arrays
    int n=aLimites.size();
    limites=new double[n];
    coeffr=new double[n];
    coeffn=new double[n];
    for(int i=0;i<n;i++){
      limites[i]=Double.parseDouble((String)aLimites.get(i));
      coeffr[i]=Double.parseDouble((String)aCoeffR.get(i));
      coeffn[i]=Double.parseDouble((String)aCoeffN.get(i));
    }//for
  }

  void mnuCalculer_actionPerformed(ActionEvent e) {
    // Berechnung der Steuer
     // Lohnprüfung
    int salaire=0;
    try{
      salaire=Integer.parseInt(txtSalaire.getText().trim());
      if(salaire<0) throw new Exception();
    }catch (Exception ex){
       // Fehlermeldung
      txtStatus.setText("Salaire incorrect. Recommencez");
       // Fokus auf fehlerhaftes Feld
      txtSalaire.requestFocus();
       // Zurück zur Benutzeroberfläche
      return;
    }
     // Anzahl der Kinder
    Integer InbEnfants=(Integer)spinEnfants.getValue();
     // Steuerberechnung
    lblImpots.setText(""+objImpots.calculer(rdOui.isSelected(),InbEnfants.intValue(),salaire));
     // Statusmeldung löschen
    txtStatus.setText("");
  }

  void txtSalaire_caretUpdate(CaretEvent e) {
     // Das Gehalt hat sich geändert – das Menü „Berechnen“ wird aktualisiert
    mnuCalculer.setEnabled(! txtSalaire.getText().trim().equals(""));
  }

  void mnuEffacer_actionPerformed(ActionEvent e) {
    // Formular zurücksetzen
    rdNon.setSelected(true);
    spinEnfants.getModel().setValue(new Integer(0));
    txtSalaire.setText("");
    mnuCalculer.setEnabled(false);
    lblImpots.setText("");
  }
}

Wir haben hier eine Komponente verwendet, die erst ab JDK 1.4 verfügbar ist: die JSpinner. Es handelt sich um einen Inkrementierer, mit dem der Benutzer hier die Anzahl der untergeordneten Elemente festlegen kann. Diese Swing-Komponente war in der Swing-Komponentenleiste von JBuilder 6, die für den Test verwendet wurde, nicht verfügbar. Das hindert jedoch nicht an ihrer Verwendung, auch wenn die Vorgehensweise etwas komplizierter ist als bei den in der Komponentenleiste verfügbaren Komponenten. Tatsächlich kann die Komponente JSpinner während der Entwurfsphase nicht auf das Formular gezogen werden. Dies muss zur Laufzeit erfolgen. Sehen wir uns den Code an, der dies bewirkt:

     // Spinner „Kinder“ – Eingabe zwischen 0 und 20 Kindern
    spinEnfants=new JSpinner(new SpinnerNumberModel(0,0,20,1));
    spinEnfants.setBounds(new Rectangle(137,60,40,27));
    contentPane.add(spinEnfants);

Die erste Zeile erstellt die Komponente JSpinner. Diese Komponente kann für verschiedene Zwecke verwendet werden und nicht nur, wie hier, als Inkrementierer für Ganzzahlen. Das Argument des Konstruktors JSpinner ist hier ein Modell für einen Zahleninkrementierer, der vier Parameter akzeptiert (Wert, Min, Max, Inkrement). Die Komponente hat folgende Form:

Image

valeur
in der Komponente angezeigter Anfangswert
min
in der Komponente anzeigbarer Mindestwert
max
in der Komponente anzeigbarer Maximalwert
incrément
Inkrementwert des angezeigten Werts bei Verwendung der Auf-/Ab-Pfeile der Komponente

Der Wert der Komponente wird über ihre Methode getValue abgerufen, die einen Typ Object zurückgibt. Daher sind einige Typumwandlungen erforderlich, um die benötigte Ganzzahl zu erhalten:

     // Anzahl der Kinder
    Integer InbEnfants=(Integer)spinEnfants.getValue();
     // Steuerberechnung
    lblImpots.setText(""+objImpots.calculer(rdOui.isSelected(),
      InbEnfants.intValue(),salaire));

Sobald die Komponente JSpinner definiert ist, wird sie im Fenster platziert:

    spinEnfants.setBounds(new Rectangle(137,60,40,27));
    contentPane.add(spinEnfants);

Zunächst muss der Benutzer die Menüoption Initialiser verwenden, die ein Objekt impots mit dem Konstruktor erstellt

    public impots(double[] LIMITES, double[] COEFFR, double[] COEFFN) throws Exception

der Klasse impots erstellt. Zur Erinnerung: Diese Klasse wurde im Kapitel über Klassen als Beispiel definiert. Bei Bedarf kann dort nachgeschlagen werden. Die drei für den Konstruktor erforderlichen Arrays werden anhand des Inhalts einer Textdatei mit folgendem Format gefüllt:

12620.0
0
0
13190
0,05
631
15640
0,1
1290,5
24.740
0,15
2072,5
31.810
0,2
3309,5
39.970
0,25
4900
48360
0,3
6898,5
55.790
0,35
9316,5
92.970
0,4
12106
127.860
0,45
16.754,5
151250
0,50
23.147,5
172.040
0,55
30710
195.000
0,60
39312
0
0,65
49062

Jede Zeile enthält drei Zahlen, die durch mindestens ein Leerzeichen voneinander getrennt sind. Diese Textdatei wird vom Benutzer mithilfe einer Komponente vom Typ JFileChooser ausgewählt. Sobald das Objekt vom Typ impots erstellt wurde, muss der Benutzer lediglich die drei benötigten Angaben machen: verheiratet oder nicht, Anzahl der Kinder, Jahresgehalt, und anschließend die Methode calculer der Klasse impots aufrufen. Dieser Vorgang kann mehrmals wiederholt werden. Das Objekt vom Typ impots wird hingegen nur einmal erstellt, und zwar bei Verwendung der Option Initialiser.

5.6. Applets schreiben

5.6.1. Einführung

Wenn man eine Anwendung mit grafischer Benutzeroberfläche geschrieben hat, ist es relativ einfach, diese in applet umzuwandeln. Auf einem Rechner A gespeichert, kann sie über einen Webbrowser von einem Rechner B aus dem Internet heruntergeladen werden. Die ursprüngliche Anwendung wird so von zahlreichen Benutzern gemeinsam genutzt, und genau darin liegt der Hauptvorteil der Umwandlung einer Anwendung in ein Applet. Allerdings lässt sich nicht jede Anwendung auf diese Weise umwandeln: Um den Benutzer, der ein Applet in seinem Browser nutzt, nicht zu beeinträchtigen, ist die Umgebung des Applets reglementiert:

  • Ein Applet darf weder auf der Festplatte des Nutzers lesen noch schreiben
  • es kann nur mit dem Rechner kommunizieren, von dem aus es vom Browser heruntergeladen wurde.

Das sind erhebliche Einschränkungen. Sie bedeuten beispielsweise, dass eine Anwendung, die Informationen aus einer Datei oder einer Datenbank lesen muss, diese über eine Zwischenanwendung anfordern muss, die sich auf dem Server befindet, von dem sie heruntergeladen wurde.

Der allgemeine Aufbau einer einfachen Webanwendung sieht wie folgt aus:

Image

  • Der Client fordert ein Dokument HTML vom Webserver an, in der Regel über einen Browser. Dieses Dokument kann ein Applet enthalten, das als eigenständige grafische Anwendung innerhalb des vom Browser des Clients angezeigten Dokuments HTML läuft.
  • Dieses Applet hat Zugriff auf Daten, jedoch nur auf solche, die sich auf dem Webserver befinden. Es hat weder Zugriff auf die Ressourcen des Client-Rechners, auf dem es ausgeführt wird, noch auf die Ressourcen anderer Rechner im Netzwerk außer demjenigen, von dem es heruntergeladen wurde.

5.6.2. Die Klasse JApplet

5.6.2.1. Définition

Eine Anwendung kann von einem Webbrowser heruntergeladen werden, wenn es sich um eine Instanz der Klasse java.applet.Applet oder der Klasse javax.swing.JApplet handelt. Letztere leitet sich von der ersten ab, die wiederum von der Klasse Panel abgeleitet ist, welche wiederum von der Klasse Container abgeleitet ist. Da eine Instanz von Applet oder JApplet vom Typ container ist, kann sie daher Komponenten (Component) wie Schaltflächen, Kontrollkästchen, Listen usw. enthalten. Hier einige Hinweise zur Funktion der verschiedenen Methoden:

Methode
Funktion
public void destroy();
löscht die Applet-Instanz
public AppletContext getAppletContext();
Ruft den Ausführungskontext des Applets ab (das Dokument „HTML“, in dem es sich befindet, andere Applets desselben Dokuments usw.)
public String getAppletInfo();
gibt eine Zeichenkette zurück, die Informationen über das Applet enthält
public AudioClip getAudioClip(URL url);
lädt die durch URL angegebene Audiodatei
public AudioClip getAudioClip(URL url, String name);
Lädt die durch URL/name angegebene Audiodatei
public URL getCodeBase();
gibt das URL des Applets zurück
public URL getDocumentBase();
gibt das Dokument URL aus, das das Applet HTML enthält
public Image getImage(URL url);
ruft das durch URL angegebene Bild ab
public Image getImage(URL url, String name);
ruft das durch URL/name angegebene Bild ab
public String getParameter(String name);
Ruft den Wert des Parameters name ab, der im Tag <applet> des Dokuments HTML enthalten ist, das das Applet enthält.
public void init();
Diese Methode wird vom Browser beim ersten Start des Applets aufgerufen
public boolean isActive();
Status des Applets
public void play(URL url);
Spielt die durch URL angegebene Audiodatei ab
public void play(URL url, String name);
spielt die durch UR/name angegebene Audiodatei ab
public void resize(Dimension d);
legt die Größe des Applet-Rahmens fest
public void resize(int width, int height);
dasselbe
public final void setStub(AppletStub stub);
 
public void showStatus(String msg);
Zeigt eine Meldung in der Statusleiste des Applets an
public void start();
Diese Methode wird vom Browser bei jeder Anzeige des Dokuments, das das Applet enthält, aufgerufen
public void stop();
Diese Methode wird vom Browser jedes Mal aufgerufen, wenn das Dokument, das das Applet enthält, zugunsten eines anderen verlassen wird (Wechsel von URL durch den Benutzer)

Die Klasse JApplet hat einige Verbesserungen gegenüber der Klasse Applet mit sich gebracht, insbesondere die Möglichkeit, Komponenten der Klassen JMenuBar und c.a.d zu enthalten. Menüs, was mit der Klasse Applet nicht möglich war.

5.6.2.2. Ausführung eines Applets: die Methoden init, start und stop

Wenn ein Browser ein Applet lädt, ruft er drei Methoden des Applets auf:

init
Diese Methode wird beim ersten Laden des Applets aufgerufen. Hier werden daher die für die Anwendung erforderlichen Initialisierungen vorgenommen.
start
Diese Methode wird jedes Mal aufgerufen, wenn das Dokument, das das Applet enthält, zum aktuellen Dokument des Browsers wird. Wenn ein Benutzer also ein Applet lädt, werden die Methoden `init` und `start` in dieser Reihenfolge ausgeführt. Wenn er das Dokument verlässt, um ein anderes anzuzeigen, wird die Methode `stop` ausgeführt. Kehrt er später zu diesem Dokument zurück, wird die Methode `start` ausgeführt.
stop
Diese Methode wird jedes Mal aufgerufen, wenn der Benutzer das Dokument verlässt, das das Applet enthält.

Bei vielen Applets ist lediglich die Methode „init“ erforderlich. Die Methoden „start“ und „stop“ sind nur dann notwendig, wenn die Anwendung Aufgaben (Threads) startet, die parallel und kontinuierlich laufen – oft ohne Wissen des Benutzers. Wenn dieser das Dokument verlässt, verschwindet der sichtbare Teil der Anwendung, doch diese Hintergrundaufgaben laufen weiter. Das ist oft unnötig. Man nutzt daher den Aufruf der Methode stop durch den Browser, um sie anzuhalten. Kehrt der Benutzer zum Dokument zurück, nutzt man den Aufruf der Methode start durch den Browser, um sie wieder zu starten.

Nehmen wir zum Beispiel ein Applet, das eine Uhr in seiner grafischen Benutzeroberfläche enthält. Diese wird von einem Hintergrundauftrag (Thread) verwaltet. Wenn der Benutzer im Browser die Seite des Applets verlässt, ist es unnötig, die Uhr weiterlaufen zu lassen, da sie nicht mehr sichtbar ist: In der „stop“-Methode des Applets wird der Thread, der die Uhr verwaltet, angehalten. In der Methode „start“ wird der Thread neu gestartet, damit der Benutzer, wenn er zur Applet-Seite zurückkehrt, eine Uhr vorfindet, die die richtige Uhrzeit anzeigt.

5.6.3. Umwandlung einer grafischen Anwendung in ein Applet

Wir gehen hier davon aus, dass diese Umwandlung möglich ist, d. h., dass sie die Ausführungsbeschränkungen von Applets erfüllt. Eine Anwendung wird über die Methode main einer ihrer Klassen gestartet:


public class application{
    
    public static main void(String arg[]){
        
    }
    
}// Ende der Klasse

Eine solche Anwendung wird wie folgt in ein Applet umgewandelt:

import java.applet.JApplet;

public class application extends JApplet{
    
    public void init(){
        
    }
    
}// Ende der Klasse

Es ist Folgendes zu beachten:

  1. Die Klasse application leitet sich nun von der Klasse JApplet ab.
  2. Die Methode main wird durch die Methode init ersetzt.

Als Beispiel greifen wir eine bereits behandelte Anwendung wieder auf: die Listenverwaltung.

Image

Dieses Fenster enthält folgende Komponenten:

Nr.
Typ
Name
Funktion
1
JTextField
txtSaisie
Eingabefeld
2
JList
jList1
Liste in einem Container jScrollPane1
3
JList
jList2
Liste in einem Container jScrollPane2
4
JButton
cmd1To2
überträgt die ausgewählten Elemente aus Liste 1 in Liste 2
5
JButton
cmd2To1
führt den umgekehrten Vorgang aus
6
JButton
cmdRaz1
Liste 1 leeren
7
JButton
cmdRaz2
Liste 2 löschen

Der Aufbau der Anwendung sah wie folgt aus:

public class interfaceAppli extends JFrame {
  JPanel contentPane;
  JLabel jLabel1 = new JLabel();
  JLabel jLabel2 = new JLabel();
  JLabel jLabel3 = new JLabel();
  JTextField txtSaisie = new JTextField();
  JButton cmd1To2 = new JButton();
  JButton cmd2To1 = new JButton();
  DefaultListModel v1=new DefaultListModel();
  DefaultListModel v2=new DefaultListModel();
  JList jList1 = new JList(v1);
  JList jList2 = new JList(v2);
  JScrollPane jScrollPane1 = new JScrollPane();
  JScrollPane jScrollPane2 = new JScrollPane();
  JButton cmdRaz1 = new JButton();
  JButton cmdRaz2 = new JButton();
  JLabel jLabel4 = new JLabel();

   /**Rahmen erstellen*/
  public interfaceAppli() {
    enableEvents(AWTEvent.WINDOW_EVENT_MASK);
    try {
      jbInit();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  }//interfaceAppli

   /**Komponente initialisieren*/
  private void jbInit() throws Exception  {
    ...
    txtSaisie.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(ActionEvent e) {
        txtSaisie_actionPerformed(e);
      }
    });
        ...
         // Jlist1 wird in den Container jScrollPane1 eingefügt
    jScrollPane1.getViewport().add(jList1, null);
        // Jlist2 wird in den Container jScrollPane2 eingefügt
    jScrollPane2.getViewport().add(jList2, null);
        ...
  }
   /**Ersetzt, damit wir das Fenster schließen können, wenn es geschlossen wird*/
  protected void processWindowEvent(WindowEvent e) {
...
  }

  void txtSaisie_actionPerformed(ActionEvent e) {
.............
}//Klasse
  void cmd1To2_actionPerformed(ActionEvent e) {
..........
  }//Übertragung
  void cmdRaz1_actionPerformed(ActionEvent e) {
    // Liste 1 leeren
    v1.removeAllElements();
  }//Befehl „Raz1“

  void cmdRaz2_actionPerformed(ActionEvent e) {
    // Liste 2 leeren
    v2.removeAllElements();
  }///Befehl „Raz2“

Um die Klasse appli in applet umzuwandeln, gehen Sie wie folgt vor:

  • Ändern Sie die vorherige Klasse interfaceAppli so, dass sie nicht mehr von JFrame, sondern von JApplet abgeleitet ist:
public class interfaceAppli extends JApplet {
  • Die Anweisung, die den Titel des Fensters JFrame festlegt, löschen. Ein Applet JApplet hat keine Titelleiste
    // this.setTitle("JList");
  • Den Konstruktor in eine Methode umwandeln (init) und in dieser Methode die Fensterereignisbehandlung entfernen (WindowListener, ...). Ein Applet ist ein Container, dessen Größe nicht geändert und der nicht geschlossen werden kann.
   /**Rahmen erstellen*/
  public init() {
    // enableEvents(AWTEvent.WINDOW_EVENT_MASK);
    try {
      jbInit();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  }//interfaceAppli
  • Die Methode processWindowEvent muss gelöscht oder auskommentiert werden
   /**Ersetzt, damit wir das Programm beenden können, wenn das Fenster geschlossen wird*/
  //protected void processWindowEvent(WindowEvent e) {
  //  super.processWindowEvent(e);
  //  if (e.getID() == WindowEvent.WINDOW_CLOSING) {
  //    System.exit(0);
  //  }
  // }

Als Beispiel wird der vollständige Code des Applets angegeben, mit Ausnahme des Teils, der automatisch von JBuilder generiert wurde

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class interfaceAppli extends JApplet {
  JPanel contentPane;
  JLabel jLabel1 = new JLabel();
  JLabel jLabel2 = new JLabel();
  JLabel jLabel3 = new JLabel();
  JTextField txtSaisie = new JTextField();
  JButton cmd1To2 = new JButton();
  JButton cmd2To1 = new JButton();
  DefaultListModel v1=new DefaultListModel();
  DefaultListModel v2=new DefaultListModel();
  JList jList1 = new JList(v1);
  JList jList2 = new JList(v2);
  JScrollPane jScrollPane1 = new JScrollPane();
  JScrollPane jScrollPane2 = new JScrollPane();
  JButton cmdRaz1 = new JButton();
  JButton cmdRaz2 = new JButton();
  JLabel jLabel4 = new JLabel();

   /**Rahmen erstellen*/
  public void init() {
    // enableEvents(AWTEvent.WINDOW_EVENT_MASK);
    try {
      jbInit();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
  }//interfaceAppli

   /**Komponente initialisieren*/
  private void jbInit() throws Exception  {
    //setIconImage(Toolkit.getDefaultToolkit().createImage(interfaceAppli.class.getResource("[Votre icône]")));
    contentPane = (JPanel) this.getContentPane();
    contentPane.setLayout(null);
    this.setSize(new Dimension(400, 308));
    // this.setTitle("JList");
    jScrollPane1.setBounds(new Rectangle(37, 133, 124, 101));
    jScrollPane2.setBounds(new Rectangle(232, 132, 124, 101));
.............
  }

  void txtSaisie_actionPerformed(ActionEvent e) {
     // Der eingegebene Text wurde validiert
     // er wird ohne führende und abschließende Leerzeichen zurückgegeben
    String texte=txtSaisie.getText().trim();
     // Wenn er leer ist, wird er verworfen
    if(texte.equals("")){
      // Fehlermeldung
      JOptionPane.showMessageDialog(this,"Vous devez taper un texte",
        "Erreur",JOptionPane.WARNING_MESSAGE);
      // Ende
      return;
    }//if
    // wenn er nicht leer ist, wird er zu den Werten in Liste 1 hinzugefügt
    v1.addElement(texte);
     // und das Eingabefeld wird geleert
    txtSaisie.setText("");
  }

  void cmd1To2_actionPerformed(ActionEvent e) {
    // Übertragung der ausgewählten Elemente aus Liste 1 in Liste 2
    transfert(jList1,jList2);
  }//cmd1To2

  private void transfert(JList L1, JList L2){
      // Übertragung der in Liste 1 ausgewählten Elemente in Liste 2
       // Das Array mit den Indizes der in L1 ausgewählten Elemente wird abgerufen
      int[] indices=L1.getSelectedIndices();
      // Was ist zu tun?
      if (indices.length==0) return;
      // Die Werte aus L1 werden abgerufen
      DefaultListModel v1=(DefaultListModel)L1.getModel();
      // sowie die aus L2
      DefaultListModel v2=(DefaultListModel)L2.getModel();
      for(int i=indices.length-1;i>=0;i--){
        // Die in L1 ausgewählten Werte werden zu L2 hinzugefügt
        v2.addElement(v1.elementAt(indices[i]));
        // Die aus L1 in L2 kopierten Elemente müssen aus L1 gelöscht werden
        v1.removeElementAt(indices[i]);
      }//für
  }//Übertragung

  private void affiche(String message){
    // zeigt Meldung an
      JOptionPane.showMessageDialog(this,message,
        "Suivi",JOptionPane.INFORMATION_MESSAGE);
  }// zeigt an

  void cmd2To1_actionPerformed(ActionEvent e) {
    // Übertragung der ausgewählten Elemente aus jList2 nach jList1
      transfert(jList2,jList1);
  }//cmd2TO1

  void cmdRaz1_actionPerformed(ActionEvent e) {
    // Liste 1 leeren
    v1.removeAllElements();
  }//Befehl „Raz1“

  void cmdRaz2_actionPerformed(ActionEvent e) {
    // Liste 2 löschen
    v2.removeAllElements();
  }//Befehl „Raz2“

}//Klasse

Der Quellcode dieses Applets kann kompiliert werden. Dies geschieht hier mit JDK, ohne JBuilder.

E:\data\serge\Jbuilder\interfaces\JApplets\1>javac.bat interfaceAppli.java

E:\data\serge\Jbuilder\interfaces\JApplets\1>dir
12/06/2002  16:40                6 148 interfaceAppli.java
12/06/2002  16:41                  527 interfaceAppli$1.class
12/06/2002  16:41                  525 interfaceAppli$2.class
12/06/2002  16:41                  525 interfaceAppli$3.class
12/06/2002  16:41                  525 interfaceAppli$4.class
12/06/2002  16:41                  525 interfaceAppli$5.class
12/06/2002  16:41                4 759 interfaceAppli.class

Die Anwendung kann mit dem Programm AppletViewer aus dem Paket JDK getestet werden, das die Ausführung von Applets oder eines Browsers ermöglicht. Dazu muss das Dokument HTML appli.htm erstellt werden, das das folgende Applet enthält:

<html>
    <head>
        <title>listes swing</title>
    </head>
    <body>
        <applet 
        code="interfaceAppli.class"
      width="400"
      height="300">
        </applet>
    </body>
</html>

Hier handelt es sich um ein klassisches HTML-Dokument, abgesehen vom Vorhandensein des Applet-Tags. Dieses wurde mit drei Parametern verwendet:

code="interfaceAppli.class"
Name der kompilierten JAVA-Klasse, die zum Ausführen des Applets geladen werden soll
width="400"
Breite des Applet-Rahmens im Dokument
height="300"
Höhe des Applet-Frames im Dokument

Nachdem die Datei „appli.htm“ erstellt wurde, kann sie mit dem Programm „appletviewer“ aus dem Ordner „JDK“ oder mit einem Browser geladen werden. Geben Sie in einem DOS-Fenster den folgenden Befehl im Ordner der Datei „appli.htm“ ein:

appletviewer appli.htm

Hier wird davon ausgegangen, dass sich das Verzeichnis der ausführbaren Datei appletviewer.exe im Verzeichnis PATH des DOS-Fensters befindet; andernfalls müsste der vollständige Pfad zur ausführbaren Datei appletviewer.exe angegeben werden. Es erscheint das folgende Fenster:

Image

Die Ausführung des Applets wird mit der Option Applet/Quitter beendet. Testen wir nun das Applet mit einem Browser. Dieser muss eine Java 2-Virtual Machine verwenden, um die Swing-Komponenten anzeigen zu können. Bis vor kurzem (2001) stellte diese Anforderung ein Problem dar, da Sun JDK-Dateien herausgab, denen die Browserhersteller nur mit großer Verzögerung folgten. Schließlich hat Sun dieses Hindernis beseitigt, indem es den Nutzern eine Anwendung namens „Java-Plugin“ zur Verfügung stellte, die es den Browsern Internet Explorer und Netscape Navigator ermöglicht, die neuesten von Sun veröffentlichten JRE (JRE = Java Runtime Environment) zu nutzen. Die folgenden Tests wurden mit IE 5.5 in Verbindung mit dem Java-Plugin 1.4 durchgeführt.

Eine erste Möglichkeit, das Applet interfaceAppli.class zu testen, besteht darin, die Datei HTML appli.htm durch Doppelklick direkt im Browser zu laden. Der Browser zeigt dann die Seite HTML und ihr Applet ohne Hilfe eines Webservers an:

Image

Anhand von URL (1) ist ersichtlich, dass die Datei direkt in den Browser geladen wurde. Im folgenden Beispiel wurde die Datei appli.htm von einem Apache-Webserver angefordert, der auf Port 81 des lokalen Rechners läuft:

Image

5.6.4. Die Formatierungsoption <applet> in einem HTML-Dokument

Wir haben gesehen, dass in einem Dokument mit der Nummer HTML das Applet durch den Formatierungsbefehl (Tag) <applet> referenziert wurde. Dieser Befehl kann verschiedene Parameter haben:

<applet
    code=
    width=
    height=
    codebase=
    align=
    hspace=
    vspace=
alt=
>
    <param name1=nom1 value=val1>
    <param name2=nom2 value=val2>
    texte
>
</applet>

Die Parameter haben folgende Bedeutung:

Parameter
Bedeutung
code
obligatorisch – Name der auszuführenden .class-Datei
width
erforderlich – Breite des Applets im Dokument
height
erforderlich – Höhe …
codebase
optional – URL des Verzeichnisses, das das auszuführende Applet enthält. Wenn „codebase“ nicht angegeben ist, wird das Applet im Verzeichnis des HTML-Dokuments gesucht, das darauf verweist
align
optional – Positionierung (LEFT, RiGHT, CENTER) des Applets im Dokument
hspace
optional – horizontaler Rand um das Applet, angegeben in Pixeln
vspace
optional – vertikaler Rand um das Applet, angegeben in Pixeln
alt
optional – Text, der anstelle des Applets angezeigt wird, wenn der Browser es nicht laden kann
param
optional – an das Applet übergebener Parameter, der dessen Namen (name) und Wert (value) angibt. Das Applet kann den Wert des Parameters „name1“ über „val1=getParameter(„name1“)“ abrufen
Es können beliebig viele Parameter verwendet werden
texte
optional – wird von jedem Browser angezeigt, der kein Applet ausführen kann, beispielsweise weil er keine Java-Virtual-Machine besitzt.

Nehmen wir ein Beispiel, um die Übergabe von Parametern an ein Applet zu veranschaulichen:

<html>
    <head>
        <title>paramètres applet</title>
    </head>
    <body>
        <applet code="interfaceParams.class" width="400" height="300">
      <param name="param1" value="val1">
      <param name="param2" value="val2">      
        </applet>
    </body>
</html>

Der Java-Code des Applets interfaceParams wurde wie zuvor beschrieben generiert. Es wurde eine Anwendung JBuilder erstellt und anschließend wurden die oben genannten Änderungen vorgenommen:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class interfaceParams extends JApplet {
  JPanel contentPane;
  JScrollPane jScrollPane1 = new JScrollPane();
  JLabel jLabel1 = new JLabel();
  DefaultListModel params=new DefaultListModel();
  JList lstParams = new JList(params);

  //Rahmen erstellen
  public void init() {
    // enableEvents(AWTEvent.WINDOW_EVENT_MASK);
    try {
      jbInit();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
     // weitere Initialisierungen
    moreInit();
  }

   // Initialisierungen
  public void moreInit(){
     // zeigt die Werte der Applet-Parameter an
    params.addElement("nom=param1 valeur="+getParameter("param1"));
    params.addElement("nom=param2 valeur="+getParameter("param2"));
  }//Weitere Initialisierungen

   //Komponente initialisieren
  private void jbInit() throws Exception  {
............
    this.setSize(new Dimension(205, 156));
    //this.setTitle("Parameter eines Applets");
    jScrollPane1.setBounds(new Rectangle(19, 53, 160, 73));
............
 }
}

Die Ausführung mit AppletViewer:

Image

5.6.5. Zugriff auf entfernte Ressourcen aus einem Applet heraus

Viele Anwendungen müssen auf Informationen in Dateien oder Datenbanken zugreifen. Wir haben bereits erwähnt, dass ein Applet keinen Zugriff auf die Ressourcen des Rechners hat, auf dem es ausgeführt wird. Das ist eine vernünftige Maßnahme. Andernfalls würde es ausreichen, ein Applet zu schreiben, um die Festplatte derjenigen auszuspionieren, die es laden. Das Applet hat jedoch Zugriff auf die Ressourcen des Servers, von dem es heruntergeladen wurde, beispielsweise auf Dateien. Das werden wir nun betrachten.

5.6.5.1. Die Klasse URL

Jede Java-Anwendung kann mithilfe der Klasse java.net.URL (URL = Uniform Resource Locator) eine Datei lesen, die sich auf einem Rechner im Netzwerk befindet. Ein URL identifiziert eine Ressource im Netzwerk, den Rechner, auf dem sie sich befindet, sowie das Protokoll und den Kommunikationsport, die zum Abrufen der Ressource verwendet werden sollen, in der Form:

Protokoll:Port//Rechner/Datei

So bezeichnet beispielsweise der URL http://www.ibm.com/index.html die Datei index.html auf dem Rechner www.ibm.com. Der Zugriff erfolgt über das Protokoll http. Der Port ist nicht angegeben: Der Browser verwendet Port 80, den Standardport des HTTP-Dienstes.

Sehen wir uns einige Elemente der Klasse URL genauer an:

public URL(String spec)
erstellt eine Instanz von URL anhand einer Zeichenkette vom Typ „protokoll:port//Rechner/Datei“ – löst eine Ausnahme aus, wenn die Syntax der Zeichenkette nicht mit einer URL übereinstimmt
  
public String getFile()
gibt das Feld „Datei“ der Zeichenkette „Protokoll:Port//Rechner/Datei“ des URL zurück
  
public String getHost()
ermöglicht es, das Feld „Rechner“ aus der Zeichenkette „Protokoll:Port//Rechner/Datei“ des URL zu extrahieren
  
public String getPort()
ermöglicht es, das Feld „port“ aus der Zeichenkette „protokoll:port//Rechner/Datei“ von URL zu extrahieren
  
public String getProtocol()
ermöglicht es, das Feld „protokoll“ aus der Zeichenkette „protokoll:port//Rechner/Datei“ von URL zu extrahieren
  
public URLConnection openConnection()
öffnet die Verbindung zum Remote-Rechner getHost() auf dessen Port getPort() gemäß dem Protokoll getProtocol(), um die Datei getFile() zu lesen. Löst eine Ausnahme aus, wenn die Verbindung nicht geöffnet werden konnte
  
public final InputStream openStream()
Abkürzung für openConnection().getInputStream(). Ermöglicht das Abrufen eines Eingabestroms, aus dem der Inhalt der Datei getFile() gelesen werden kann. Löst eine Ausnahme aus, wenn der Strom nicht abgerufen werden konnte
  
public String toString()
Gibt die Identität der Instanz von URL zurück

Hier gibt es zwei Methoden, die für uns von Interesse sind:

  • public URL(String spec) zur Angabe der zu verarbeitenden Datei
  • public final InputStream openStream() zur Verarbeitung der Datei

5.6.5.2. Ein Beispiel für die Befehlszeile

Wir schreiben ein Java-Programm ohne grafische Benutzeroberfläche, das den Inhalt einer URL, die als Parameter übergeben wird, auf dem Bildschirm anzeigt. Ein Beispiel für einen Aufruf könnte wie folgt aussehen:

    DOS> java urlcontenu http://istia.univ-angers.fr/index.html

Das Programm ist relativ einfach:


import java.net.*;             // für die Klasse URL
import java.io.*;                // für die Streams

public class urlcontenu{

// zeigt den Inhalt des als Argument übergebenen URL an
// Dieser Inhalt muss aus Text bestehen, damit er lesbar ist

  public static void main (String arg[]){
    // Überprüfung der Argumente
    if(arg.length==0){
      System.err.println("Syntaxe pg url");
      System.exit(0);
    }
    
    try{
      // Erstellung von URL      
      URL url=new URL(arg[0]);
      // Inhalt wird gelesen
      try{
        // Erstellung des Eingabestroms
        BufferedReader is=new BufferedReader(new InputStreamReader(url.openStream()));
        try{
          // Einlesen der Textzeilen aus dem Eingabestrom
          String ligne;
          while((ligne=is.readLine())!=null)
            System.out.println(ligne);
        } catch (Exception e){
            System.err.println("Erreur lecture : " +e);
        }
        finally{
          try { is.close(); } catch (Exception e) {}
        }
      } catch (Exception e){
          System.err.println("Erreur openStream : " +e);
      }
    } catch (Exception e){
      System.err.println("Erreur création URL : " +e);
    }
  }// Ende der Hauptschleife
}// Ende der Klasse

Nachdem überprüft wurde, dass tatsächlich ein Argument vorhanden ist, wird versucht, mit diesem ein URL zu erstellen:


// Erstellung des URL      
      URL url=new URL(arg[0]);

Diese Erstellung kann fehlschlagen, wenn das Argument nicht der Syntax von URL protocole:port//machine/fichier entspricht. Liegt ein syntaktisch korrektes URL vor, wird versucht, einen Eingabestrom zu erstellen, aus dem Textzeilen gelesen werden können. Der von einer URL URL.openStream() bereitgestellte Eingabestrom liefert einen Strom vom Typ InputStream, bei dem es sich um einen zeichenorientierten Strom handelt: Das Einlesen erfolgt zeichenweise, und die Zeilen müssen selbst gebildet werden. Um Textzeilen lesen zu können, muss die Methode readLine der Klassen BufferedReader oder DataInputStream.On verwendet werden; hier wurde BufferedReader gewählt. Nun müssen wir nur noch den Datenstrom InputStream aus URL in den Datenstrom BufferedReader umwandeln. Dies geschieht durch die Erstellung eines Zwischendatenstroms InputStreamReader:


BufferedReader is=new BufferedReader(new InputStreamReader(url.openStream()));

Die Erstellung dieses Flusses kann fehlschlagen. Die entsprechende Ausnahme wird behandelt. Sobald der Fluss vorliegt, müssen wir nur noch die Textzeilen daraus auslesen und diese auf dem Bildschirm anzeigen.


            String ligne;
         while((ligne=is.readLine())!=null)
                System.out.println(ligne);

Auch hier kann das Einlesen eine Ausnahme auslösen, die abgefangen werden muss. Hier ist ein Beispiel für die Ausführung des Programms, das eine lokale URL anfordert:

E:\data\serge\Jbuilder\interfaces\JApplets\3>java urlcontenu http://localhost
<html>

<head>


<title>Bienvenue dans le Serveur Web personnel</title>
</head>

<body bgcolor="#FFFFFF" link="#0080FF" vlink="#0080FF"
topmargin="0" leftmargin="0">

<table border="0" cellpadding="0" cellspacing="0" width="100%"
bgcolor="#000000">
............
                </table>
                </center></div></td>
            </tr>
        </table>
        </td>
    </tr>
</table>
</body>
</html>

5.6.5.3. Ein grafisches Beispiel

Die grafische Benutzeroberfläche sieht wie folgt aus:

Image

Nummer
Name
Typ
Rolle
1
txtURL
JTextField
URL – bitte lesen
2
btnCharger
JButton
Schaltfläche zum Starten der Wiedergabe von URL
3
JScrollPane1
JScrollPane
Laufband
4
lstURL
JList
Liste mit dem Inhalt des angeforderten URL

Bei der Ausführung erhalten wir ein Ergebnis, das dem des Konsolenprogramms ähnelt:

Image

Der relevante Code der Anwendung lautet wie folgt:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.net.*;
import java.io.*;

public class interfaceURL extends JFrame {
  JPanel contentPane;
  JLabel jLabel1 = new JLabel();
  JTextField txtURL = new JTextField();
  JButton btnCharger = new JButton();
  JScrollPane jScrollPane1 = new JScrollPane();
  DefaultListModel lignes=new DefaultListModel();
  JList lstURL = new JList(lignes);

  //Rahmen erstellen
  public interfaceURL() {
..............
  }

   //Komponente initialisieren
  private void jbInit() throws Exception  {
..............
  }

   //Ersetzt, damit wir das Programm beenden können, wenn das Fenster geschlossen wird
  protected void processWindowEvent(WindowEvent e) {
...................
  }

  void txtURL_caretUpdate(CaretEvent e) {
    // legt den Status der Schaltfläche „Laden“ fest
    btnCharger.setEnabled(! txtURL.getText().trim().equals(""));
  }

  void btnCharger_actionPerformed(ActionEvent e) {
    // zeigt den Inhalt von URL in der Liste an
    try{
      afficherURL(txtURL.getText().trim());
    }catch(Exception ex){
       // Fehleranzeige
      JOptionPane.showMessageDialog(this,"Erreur : " + ex.getMessage(),"Erreur",JOptionPane.ERROR_MESSAGE);
    }//Try-Catch
  }

  private void afficherURL(String strURL) throws Exception {
    // zeigt den Inhalt von URL und strURL in der Liste an
     // Es wird keine Ausnahme speziell behandelt. Sie werden lediglich weitergeleitet

     // Erstellung des URL
    URL url=new URL(strURL);
     // Erstellung des Eingabestroms
    BufferedReader IN=new BufferedReader(new InputStreamReader(url.openStream()));
    // Lesen der Textzeilen aus dem Eingabestrom
    String ligne;
    while((ligne=IN.readLine())!=null)
      lignes.addElement(ligne);
     // Schließen des Lesestroms
    IN.close();
  }
}

5.6.5.4. Ein Applet

Die vorstehende grafische Anwendung wird, wie bereits mehrfach gezeigt, in ein Applet umgewandelt. Das Applet wird in ein Dokument HTML appliURL.htm eingefügt:

<html>
  <head>
    <title>Applet lisant une URL</title>
  </head>
  <body>
    <h1>Applet lisant une URL</h1>
    <applet
      code="appletURL.class"
      width="400"
      height="300"
    >
    </applet>
  </body>
</html>

Image

Im obigen Beispiel hat der Browser die URL „URLhttp://localhost:81/Japplets/2/appliURL.htm“ von einem Webserver mit der Adresse „apache“ angefordert, der auf Port 81 läuft. Das Applet wurde daraufhin im Browser angezeigt. Darin wurde erneut die URL „URL http://localhost:81/Japplets/2/appliURL.htm“ aufgerufen, um zu überprüfen, ob tatsächlich die von uns erstellte Datei „appliURL.htm“ abgerufen wurde. Versuchen wir nun, eine URL-Datei zu laden, die nicht von dem Rechner stammt, der das Applet bereitgestellt hat (hier localhost):

Image

Das Laden der Datei „URL“ wurde abgelehnt. Hier zeigt sich die Einschränkung bei Applets: Sie können nur auf die Netzwerkressourcen des Rechners zugreifen, von dem aus sie heruntergeladen wurden. Es gibt eine Möglichkeit für das Applet, diese Einschränkung zu umgehen, nämlich die Netzwerkanfragen an ein Serverprogramm weiterzuleiten, das sich auf dem Rechner befindet, von dem es heruntergeladen wurde. Dieses Programm führt die Netzwerkanfragen anstelle des Applets durch und sendet ihm die Ergebnisse zurück. Man bezeichnet dies als Relaisprogramm.

5.7. Das Applet IMPOTS

Wir werden nun die grafische Anwendung IMPOTS in ein Applet umwandeln. Dies ist insofern interessant, als die Anwendung dadurch für jeden Internetnutzer verfügbar wird, der über einen Browser und ein Java-Plugin 1.4 verfügt (aufgrund der Komponente JSpinner). Unsere Anwendung wird somit weltweit zugänglich... Diese Änderung erfordert etwas mehr als die mittlerweile klassische Umwandlung von einer grafischen Anwendung in ein Applet. Die Anwendung nutzt eine Menüoption Initialiser, deren Zweck darin besteht, den Inhalt einer lokalen Datei zu lesen. Wenn man sich jedoch eine Webanwendung vorstellt, wird deutlich, dass dieses Schema nicht mehr zutrifft:

Image

Es liegt auf der Hand, dass sich die Daten, die die Steuertabellen definieren, auf dem Webserver und nicht auf jedem einzelnen Client-Rechner befinden werden. Die auf dem Webserver einzulesende Datei wird hier im selben Ordner wie das Applet abgelegt, und die Option Initialiser muss sie dort abrufen. Die vorangegangenen Beispiele haben gezeigt, wie dies zu bewerkstelligen ist. Um die Datendatei lokal auszuwählen, wurde zudem eine Komponente JFileChooser verwendet, die hier nicht mehr erforderlich ist.

Das Dokument HTML, das das Applet enthält, sieht wie folgt aus:

<html>
  <head>
    <title>Applet de calcul d'impôts</title>
  </head>
  <body>
    <h2>Calcul d'impôts</h2>
    <applet
      code="appletImpots.class"
      width="320"
      height="270"
    >

<param name="data" value="impots.txt">


    </applet>
  </body>
</html>

Zu beachten ist der Parameter data, dessen Wert der Name der Datei ist, die die Daten des Steuertarifs enthält. Das Dokument HTML, die Klasse appletImpots, die Klasse impots und die Datei impots.txt befinden sich alle im selben Ordner auf dem Webserver:

E:\data\serge\web\JApplets\impots>dir
12/06/2002  13:24                  247 impots.txt
13/06/2002  10:17                  654 appletImpots$2.class
13/06/2002  10:17                  653 appletImpots$3.class
13/06/2002  10:17                  653 appletImpots$4.class
13/06/2002  10:17                  651 appletImpots$5.class
13/06/2002  10:06                  651 appletImpots$6.class
13/06/2002  10:17                8 655 appletImpots.class
13/06/2002  10:17                  657 appletImpots$1.class
13/06/2002  10:24                  286 appletImpots.htm
13/06/2002  10:17                1 305 impots.class

Der Code des Applets lautet wie folgt (wir haben nur die Änderungen gegenüber der grafischen Anwendung hervorgehoben):

...........
import java.net.*;
import java.applet.Applet;

public class appletImpots extends JApplet {
  // die Komponenten des Fensters
  JPanel contentPane;
............................

   // die Attribute der Klasse
  double[] limites=null;
  double[] coeffr=null;
  double[] coeffn=null;
  impots objImpots=null;
  String urlDATA=null;

  //Rahmen erstellen
  public void init() {
    //enableEvents(AWTEvent.WINDOW_EVENT_MASK);
    try {
      jbInit();
    }
    catch(Exception e) {
      e.printStackTrace();
    }
     // weitere Initialisierungen
    moreInit();
  }

   // Formularinitialisierung
  private void moreInit(){
     // Menü „Berechnen“ deaktiviert
    mnuCalculer.setEnabled(false);
................
     // Der Name der Steuertafel-Datei wird abgerufen
    String nomFichier=getParameter("data");
    // Fehler?
    if(nomFichier==null){
       // Fehlermeldung
      txtStatus.setText("Le paramètre data de l'applet n'a pas été initialisé");
       // Die Option „Initialisieren“ wird gesperrt
      mnuInitialiser.setEnabled(false);
      // Ende
      return;
    }//if
     // URL der Daten wird festgelegt
    urlDATA=getCodeBase()+"/"+nomFichier;
  }//moreInit

   //Komponente initialisieren
  private void jbInit() throws Exception  {
...................
  }

  void mnuQuitter_actionPerformed(ActionEvent e) {
    // Die Anwendung wird beendet
    System.exit(0);
  }

  void mnuInitialiser_actionPerformed(ActionEvent e) {
    // Die Datendatei wird geladen
    try{
       // Daten lesen
      lireDATA();
       // Erstellung des Objekts „Steuern“
      objImpots=new impots(limites,coeffr,coeffn);
................
  }

  private void lireDATA() throws Exception {
     // Die Datentabellen
    ArrayList aLimites=new ArrayList();
    ArrayList aCoeffR=new ArrayList();
    ArrayList aCoeffN=new ArrayList();
    String[] champs=null;

     // Datei zum Lesen öffnen
    BufferedReader IN=new BufferedReader(new InputStreamReader(new URL(urlDATA).openStream()));
    // Die Datei wird zeilenweise gelesen
....................
  }

  void mnuCalculer_actionPerformed(ActionEvent e) {
    // Berechnung der Steuer
......................
  }

  void txtSalaire_caretUpdate(CaretEvent e) {
..........
  }

  void mnuEffacer_actionPerformed(ActionEvent e) {
...............
  }
}

Wir gehen hier nur auf die Änderungen ein, die sich daraus ergeben, dass sich die zu lesende Datendatei nun auf einem Remote-Rechner statt auf einem lokalen Rechner befindet:

Der Name der einzulesenden Datendatei „URL“ wird durch den folgenden Code ermittelt:

     // Abruf des Dateinamens des Steuertarifs
    String nomFichier=getParameter("data");
    // Fehler?
    if(nomFichier==null){
       // Fehlermeldung
      txtStatus.setText("Le paramètre data de l'applet n'a pas été initialisé");
       // Die Option „Initialisieren“ wird gesperrt
      mnuInitialiser.setEnabled(false);
      // Ende
      return;
    }//if
     // URL der Daten wird festgelegt
    urlDATA=getCodeBase()+"/"+nomFichier;

Denken wir daran, dass der Dateiname „impots.txt“ in den Parameter data des Applets übergeben wurde:

    <param name="data" value="impots.txt">

Der obige Code beginnt also damit, den Wert des Parameters data abzurufen und dabei einen möglichen Fehler zu behandeln. Wenn der Wert von URL des Dokuments HTML, das das Applet enthält, „http://localhost:81/JApplets/impots/appletImpots.htm“ lautet, dann lautet die URL der Datei impots.txt „http://localhost:81/JApplets/impots/impots.txt“. Wir müssen den Namen dieses URL ermitteln. Die Methode getCodeBase() des Applets liefert den URL des Ordners, aus dem das Dokument HTML, das das Applet enthält, abgerufen wurde, also in unserem Beispiel http://localhost:81/JApplets/impots. Mit der folgenden Anweisung lässt sich somit der URL der Datendatei bilden:

    urlDATA=getCodeBase()+"/"+nomFichier;

In der Methode lireFichier(), die den Inhalt von URL und urlData liest, wird der Eingabestrom erstellt, der das Einlesen der Daten ermöglicht:

     // Datei zum Lesen öffnen
    BufferedReader IN=new BufferedReader(new InputStreamReader(new URL(urlDATA).openStream()));

Ab diesem Zeitpunkt lässt sich nicht mehr unterscheiden, ob die Daten aus einer entfernten oder einer lokalen Datei stammen. Hier ein Beispiel für die Ausführung des Applets:

Image

5.8. Fazit

Dieses Kapitel hat

  • eine Einführung in die Erstellung grafischer Benutzeroberflächen mit JBuilder
  • die gängigsten Swing-Komponenten
  • die Erstellung von Applets

Zusammenfassend lässt sich sagen, dass

  • der von JBuilder generierte Code von Hand geschrieben werden kann. Sobald dieser Code auf die eine oder andere Weise vorliegt, reicht ein einfaches JDK aus, um ihn auszuführen, und JBuilder ist dann nicht mehr unbedingt erforderlich.
  • Die Verwendung eines Tools wie JBuilder kann zu erheblichen Produktivitätssteigerungen führen:
    • Zwar ist es möglich, den von JBuilder generierten Code von Hand zu schreiben, doch kann dies sehr zeitaufwendig sein und ist kaum sinnvoll, da die Logik der Anwendung in der Regel an anderer Stelle liegt.
    • Der generierte Code kann aufschlussreich sein. Ihn zu lesen und zu studieren ist eine gute Möglichkeit, bestimmte Methoden und Eigenschaften von Komponenten zu entdecken, die man zum ersten Mal verwendet.
    • JBuilder ist plattformübergreifend. Man behält also sein Wissen bei, wenn man von einer Plattform zur anderen wechselt. Die Möglichkeit, Programme zu schreiben, die sowohl unter Windows als auch unter Linux laufen, ist natürlich ein sehr wichtiger Produktivitätsfaktor. Dies ist jedoch Java selbst zu verdanken und nicht JBuilder.

5.9. JBuilder unter Linux

Alle vorangegangenen Beispiele wurden unter Windows 98 getestet. Man kann sich fragen, ob die geschriebenen Programme unverändert unter Linux lauffähig sind. Sofern der betreffende Linux-Rechner über die von den verschiedenen Programmen verwendeten Klassen verfügt, sind sie es. Wenn Sie beispielsweise JBuilder unter Linux installiert haben, befinden sich die erforderlichen Klassen bereits auf Ihrem Rechner. Hier sehen Sie beispielsweise, wie die Ausführung eines unserer Programme auf der Komponente JList mit JBuilder 4 unter Linux aussieht:

Im Folgenden beschreiben wir die Installation von JBuilder 4 Foundation auf einem Linux-Rechner. Die Installation auf einem Win9x-Rechner ist problemlos und entspricht dem nun beschriebenen Vorgang. Die Installation späterer Versionen unterscheidet sich wahrscheinlich davon, doch dieses Dokument kann dennoch einige nützliche Informationen enthalten.

JBuilder ist auf der Website von Inprise unter der URL http://www.inprise.com/jbuilder verfügbar

Image

Auf dieser Seite finden sich unter anderem Links für Windows und Linux. Wir beschreiben nun die Installation von JBuilder auf einem Linux-Rechner mit der grafischen Benutzeroberfläche KDE.

Wenn man dem Link „JBuilder 4 für Linux“ folgt, wird ein Formular angezeigt. Dieses füllt man aus und erhält schließlich zwei Dateien:

jb4docs_fr.tar.gz: die Dokumentation und Beispiele zu JBuilder 4

jb4fndlinux_fr.tar.gz: JBuilder 4 Foundation. Dies ist eine eingeschränkte Version des kommerziellen JBuilder 4, die jedoch für Bildungszwecke ausreicht.

Ein Aktivierungsschlüssel für die Software wird Ihnen per E-Mail zugesandt. Mit diesem Schlüssel können Sie JBuilder 4 nutzen; er wird bei der ersten Verwendung abgefragt. Sollten Sie diesen Schlüssel verlieren, können Sie zur oben genannten URL zurückkehren und dem Link „get your activation key“ folgen. Wir gehen im Folgenden davon aus, dass Sie root sind und sich im Verzeichnis der beiden oben genannten Dateien tar.gz befinden. Entpacken Sie die beiden Dateien:

[tar xvzf jb4fndlinux_fr.tar.gz]
[tar xvzf jb4docs_fr.tar.gz]
[ls -l]
drwxr-xr-x    3 nobody   nobody       4096 oct 10  2000 docs
drwxr-xr-x    3 nobody   nobody       4096 déc  5 13:00 foundation
[ls -l foundation]
-rw-r--r--    1 nobody   nobody       1128 déc  5 13:00 deploy.txt
-rwxr-xr-x    1 nobody   nobody   69035365 déc  5 13:00 fnd_linux_install.bin
drwxr-xr-x    2 nobody   nobody       4096 déc  5 13:00 images
-rw-r--r--    1 nobody   nobody      15114 déc  5 13:00 index.html
-rw-r--r--    1 nobody   nobody      23779 déc  5 13:00 license.txt
-rw-r--r--    1 nobody   nobody      75739 déc  5 13:00 release_notes.html
-rw-r--r--    1 nobody   nobody      31902 déc  5 13:00 whatsnew.html
[ls -l docs]
-rw-r--r--    1 nobody   nobody       1128 oct 10  2000 deploy.txt
-rwxr-xr-x    1 nobody   nobody   40497874 oct 10  2000 doc_install.bin
drwxr-xr-x    2 nobody   nobody       4096 oct 10  2000 images
-rw-r--r--    1 nobody   nobody       9210 oct 10  2000 index.html
-rw-r--r--    1 nobody   nobody      23779 oct 10  2000 license.txt
-rw-r--r--    1 nobody   nobody      75739 oct 10  2000 release_notes.html
-rw-r--r--    1 nobody   nobody      31902 oct 10  2000 whatsnew.html

In den beiden erstellten Verzeichnissen ist die Datei „.bin“ die Installationsdatei. Öffnen Sie außerdem mit einem Browser die Datei „index.html“ in jedem der Verzeichnisse. Dort finden Sie die Anleitung zur Installation der beiden Produkte. Beginnen wir mit der Installation von JBuilder Foundation:

[cd foundation]
[./fnd_linux_install.bin]

Es erscheint der erste Bildschirm der Installation. Es folgen zahlreiche weitere:

Image

Bestätigen Sie. Es folgt ein Bildschirm mit Erläuterungen:

Image

Führen Sie [suivant] aus.

Image

Akzeptieren Sie die Lizenzvereinbarung und führen Sie den Befehl [suivant] aus.

Image

Akzeptieren Sie den vorgeschlagenen Speicherort für JBuilder (notieren Sie sich diesen, Sie werden ihn später benötigen) und führen Sie [suivant] aus. Die Installation ist schnell abgeschlossen.

Image

Wir sind bereit für einen ersten Test. Starten Sie in KDE den Dateimanager, um zum Verzeichnis der JBuilder-Ausführungsdateien zu gelangen: /opt/jbuilder4/bin (sofern Sie JBuilder in /opt/jbuilder4 installiert haben):

Image

Klicken Sie auf das Symbol jbuilder oben. Da Sie JBuilder zum ersten Mal verwenden, müssen Sie Ihren Aktivierungsschlüssel eingeben:

Image

Füllen Sie die Felder Nom und Société aus. Klicken Sie auf „[Ajouter]“, um Ihren Aktivierungsschlüssel einzugeben. Wir weisen darauf hin, dass Ihnen dieser per E-Mail zugesandt worden sein sollte und dass Sie ihn, falls Sie ihn verloren haben, unter der URL abrufen können, unter der Sie JBuilder 4 heruntergeladen haben (siehe Beginn der Installation). Sobald Ihr Aktivierungsschlüssel akzeptiert wurde, werden Ihnen die Lizenzbedingungen angezeigt:

Image

Mit dem Befehl OK kehren Sie zu dem bereits bekannten Fenster zur Eingabe der Informationen zurück:

Image

Geben Sie OK ein, um diesen Schritt abzuschließen, der nur beim ersten Start ausgeführt wird. Anschließend erscheint die Entwicklungsumgebung von JBuilder:

Image

Beenden Sie JBuilder, um nun die Dokumentation zu installieren. Dabei werden einige Dateien installiert, die in der JBuilder-Hilfe verwendet werden, die derzeit noch unvollständig ist. Kehren Sie in das Verzeichnis zurück, in das Sie die JBuilder-Dateien tar.gz entpackt haben. Das Installationsprogramm befindet sich im Verzeichnis docs. Wechseln Sie dorthin:

[cd docs]
[ls -l]
-rw-r--r--    1 nobody   nobody       1128 oct 10  2000 deploy.txt
-rwxr-xr-x    1 nobody   nobody   40497874 oct 10  2000 doc_install.bin
drwxr-xr-x    2 nobody   nobody       4096 oct 10  2000 images
-rw-r--r--    1 nobody   nobody       9210 oct 10  2000 index.html
-rw-r--r--    1 nobody   nobody      23779 oct 10  2000 license.txt
-rw-r--r--    1 nobody   nobody      75739 oct 10  2000 release_notes.html
-rw-r--r--    1 nobody   nobody      31902 oct 10  2000 whatsnew.html

Die Installationsdatei lautet doc_install.bin, kann jedoch nicht sofort gestartet werden. Wenn man dies dennoch versucht, schlägt die Installation fehl, ohne dass man den Grund dafür versteht. Lesen Sie die Datei index.html mit einem Browser, um eine genaue Beschreibung des Installationsvorgangs zu erhalten. Das Installationsprogramm benötigt eine Java-Virtual-Machine, genauer gesagt ein Programm namens java, das sich im Verzeichnis PATH auf Ihrem Rechner befinden muss. Zur Erinnerung: PATH ist eine Unix-Variable, deren Wert in der Form rep1:rep2:...:repn die Verzeichnisse repi angibt, die bei der Suche nach einer ausführbaren Datei durchsucht werden müssen. In diesem Fall fordert das Installationsprogramm die Ausführung eines Programms mit dem Namen java an. Je nach Anzahl der virtuellen Java-Maschinen, die Sie hier und da installiert haben, können mehrere Versionen dieses Programms vorhanden sein. Logischerweise verwenden wir die von JBuilder 4 bereitgestellte Version, die sich in /opt/jbuilder4/jdk1.3/bin befindet. Um dieses Verzeichnis in die Variable PATH einzutragen:

[echo $PATH]
/usr/local/sbin:/usr/sbin:/sbin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin
[export PATH=/opt/jbuilder4/jdk1.3/bin/:$PATH]
[echo $PATH]
/opt/jbuilder4/jdk1.3/bin/:/usr/local/sbin:/usr/sbin:/sbin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/root/bin

Wir können nun die Installation der Dokumentation starten:

[./doc_install.bin]
Preparing to install...

Es handelt sich um eine grafische Installation:

Image

Sie verläuft sehr ähnlich wie bei JBuilder Foundation. Daher werden wir hier nicht näher darauf eingehen. Es gibt jedoch einen Bildschirm, den Sie nicht übersehen sollten:

Image

Das Installationsprogramm sollte normalerweise selbstständig erkennen, wo Sie JBuilder Foundation installiert haben. Ändern Sie daher die vorgeschlagene Einstellung nicht, es sei denn, sie ist falsch.

Sobald die Dokumentation installiert ist, können wir einen neuen Test mit JBuilder durchführen. Starten Sie die Anwendung wie oben beschrieben. Sobald JBuilder geöffnet ist, wählen Sie die Option „Hilfe/Hilfe-Thema“. Klicken Sie im linken Rahmen auf den Link Tutoriels:

Image

JBuilder enthält eine Reihe von Tutorials, die Ihnen den Einstieg in die Java-Programmierung erleichtern. Im Folgenden haben wir das oben genannte Tutorial „Erstellen einer Anwendung“ durchlaufen.

Image

Wählen Sie in JBuilder „Datei/Neues Projekt“. Ein Assistent zeigt Ihnen drei Bildschirme an:

Image

Wir erstellen ein einfaches Fenster mit dem Titel „Hallo Welt“. Wir nennen dieses Projekt coucou. Das Beispiel wurde mit root ausgeführt. JBuilder schlägt daraufhin vor, alle Projekte in einem Verzeichnis jbproject im Verbindungsverzeichnis von root zusammenzufassen. Das Projekt coucou wird im Verzeichnis coucou (Feld „Name des Projektverzeichnisses“) von jbproject abgelegt. Erstellen Sie [suivant].

Image

Dieser zweite Bildschirm enthält eine Übersicht über die verschiedenen Pfade Ihres Projekts. Es sind keine Änderungen erforderlich. Führen Sie [suivant] aus.

Image

Auf dem dritten Bildschirm werden Sie aufgefordert, Ihr Projekt anzupassen. Füllen Sie die Angaben aus und führen Sie den Befehl [Terminer] aus.

Führen Sie nun Fichier/Nouveau aus:

Image

Wählen Sie Application und führen Sie OK aus. Ein neuer Assistent zeigt Ihnen zwei Bildschirme an:

Image

Das Feld paquet enthält den Namen des Projekts. Im Feld „Klasse“ wird nach dem Wert nom gefragt, der der Hauptklasse des Projekts zugewiesen wird. Übernehmen Sie den oben genannten Namen und geben Sie [suivant] ein:

Image

Unsere Anwendung enthält eine zweite Java-Klasse für das Anwendungsfenster. Geben Sie dieser Klasse einen Namen. Das Feld „Titre“ ist der Titel, den Sie diesem Fenster geben möchten. Der Rahmen „options“ bietet Ihnen Optionen für Ihr Fenster. Wählen Sie alle aus und geben Sie [Terminer] ein. Sie kehren dann zur JBuilder-Umgebung zurück, die nun um die von Ihnen für Ihr Projekt eingegebenen Informationen erweitert wurde:

Image

Im linken/oberen Fenster (1) sehen Sie die Liste der Dateien, aus denen Ihr Projekt besteht. Darunter befinden sich insbesondere die beiden Klassen .java, deren Namen wir gerade vergeben haben. Im rechten Fenster (2) sehen Sie den Java-Code der Klasse coucouCadre. Im linken/unteren Fenster sehen Sie die Struktur (Klassen, Methoden, Attribute) Ihres Projekts. Es ist bereit zur Ausführung. Klicken Sie oben auf die Schaltfläche 4 oder wählen Sie „Ausführen“/„Projekt ausführen“ oder geben Sie „F9“ ein. Sie sollten das folgende Fenster erhalten:

Image

Wenn Sie auf die Option „Aide“ klicken, sollten Sie die Informationen wiederfinden, die Sie den Assistenten bei der Erstellung angegeben haben. Wir werden nicht weiter darauf eingehen. Es ist nun an der Zeit, sich in die Tutorials zu vertiefen.

Bevor wir zum Schluss kommen, wollen wir noch kurz zeigen, dass Sie nicht JBuilder und dessen grafische Benutzeroberfläche verwenden können, sondern das JDK, das JBuilder mitgebracht und unter /opt/jbuilder4/jdk1.3 abgelegt hat. Erstellen Sie die folgende Datei essai1.java:

import java.io.*;

public class essai1{
    public static void main(String args[]){
        System.out.println("coucou");
        System.exit(0);
    }
}

Kompilieren wir den Code und führen wir ihn mit dem JDK von JBuilder aus:

[ls -l *.java]
-rw-r--r--    1 root     root          135 mai  9 21:57 essai1.java
[/opt/jbuilder4/jdk1.3/bin/javac essai1.java]
[/opt/jbuilder4/jdk1.3/bin/java essai1]
coucou