MarktundTechnik Home-Page Previous Page TOC Index Next Page See Page



14. Tag:

Fenster, Vernetzung und andere Leckerbissen

von Laura Lemay

Hier sind Sie schon bei der letzten Lektion der zweiten Woche angelangt und machen sich daran, letzte Feinheiten über Applets und AWT zu lernen. Mit dem heutigen Lehrstoff können Sie eine große Vielfalt von Applets und Anwendungen in Java entwickeln. Nächste Woche vervollständigen Sie Ihre Java-Kenntnisse.

Sie beenden die letzte Lektion dieser Woche mit drei Themen:

Fenster, Menüs und Dialogfelder

Heute lernen Sie die letzten Komponenten des AWT, die in die gestrige Lektion nicht mehr hineingepaßt haben. Zusätzlich zu den Grafiken, Ereignissen, Komponenten der Benutzeroberfläche und Layoutmechanismen bietet das AWT auch Fenster, Menüs und Dialogfelder. Damit können Sie ausgewachsene Anwendungen als Teil Ihres Applets oder unabhängig entwickeln.

Fenster

Mit der Window-Klasse des AWT können Sie Fenster erstellen, die von dem Browser-Fenster, in dem das Applet erscheint, unabhängig sind. Das bedeutet, daß Sie separate Popup-Fenster mit eigenen Titeln, Menüleisten und Schaltflächen zum Vergrößern und Verkleinern erstellen können.

Die Window-Klasse enthält grundlegende Eigenschaften für Fenster. Am häufigsten werden anstelle der Window-Klasse jedoch deren Subklassen Frame und Dialog benutzt. Mit der Frame-Klasse können Sie ein voll funktionstüchtiges Fenster mit Menüleiste erstellen. Dialog dient für Dialogfelder. Sie lernen Dialogfelder später in dieser Lektion. Wir nennen Fenster in Java auch Rahmen.

Um einen Rahmen zu erstellen, verwenden Sie einen der folgenden Constructors:

Rahmen sind Container wie Panels, so daß Sie andere Komponenten mit der add()-Methode einfügen können. Das Standardlayout für Fenster ist BorderLayout:

win = new Frame("My Cool Window");


win.setLayout(new BorderLayout(10,20));
win.add("North", new Button("start"));
win.add("Center", new Button("Move"));

Um die Größe für ein neues Fenster zu setzen, verwenden Sie die resize()-Methode. Zum Festlegen der Position des Fensters benutzen Sie die move()-Methode. Die location()-Methode bezeichnet die Stelle am Bildschirm, an der sich das Applet-Fenster befindet, so daß Sie in bezug darauf ein weiteres Fenster anzeigen können (diese Methoden sind für alle Container definiert, so daß Sie sie je nach Layout für Applets, Fenster und die darin befindlichen Komponenten benutzen können):

win.resize(100,200);

Dimension d = location();

win.move(d.width + 50, d.height + 50);

Ein neu erstelltes Fenster ist zunächst unsichtbar. Sie müssen die show()-Methode anwenden, um das Fenster am Bildschirm anzuzeigen (und mit hide() können Sie es wieder verbergen):

win.show();

Listing 14.1 enthält einen Beispielcode für ein einfaches Applet mit einem Popup-Fenster (in Abb. 14.1 sehen Sie das Applet und das Fenster). Das Applet hat zwei Schaltflächen: Eine, um das Fenster anzuzeigen, und eine, um es zu verbergen. Das Fenster wurde aus der Subklasse MyFrame erstellt und hat ein einziges Label: »This is a Window«. Sie verwenden dieses einfache Fenster und das Applet in allen Beispielen dieser Lektion, so daß Sie im weiteren Verlauf besser verstehen, was hier alles passiert.

Listing 14.1: Beispiel eines Popup-Fensters

*import java.awt.*;

public class GUI extends java.applet.Applet {

   Frame window;



   public void init() {

      add(new Button("Open Window"));

      add(new Button("Close Window"));



      window = new MyFrame("A Popup Window");

      window.resize(150,150);

      window.show();

   }

   public boolean action(Event, evt, Object arg) {

      if (evt.target instanceof Button) {

         String label = (String)arg;

         if (label.equals("Open Window")) {

            if (!window.isShowing())

            window.show();

         }

         else if (label == "Close Window") {

            if (window.isShowing())

               window.hide();

         }

         return true;

      }

         else return false;

      }

   }

   class MyFrame extends Frame {

      Label l;



      MyFrame(String title) {

         super(title);

         setLayout(new GridLayout(1,1));

         l = new Label("This is a Window", Label.CENTER);

         add(l);

}

Abbildung 14.1: Fenster

Menüs

Jedes neu erstellte Fenster kann oben am Bildschirm eine eigene Menüleiste haben. Jede Menüleiste kann mehrere Menüs, und jedes Menü kann mehrere Optionen enthalten. Das AWT enthält für diese Funktionen die Klassen MenuBar, Menu und MenuItem.

Menüs und Menüleisten

Um eine Menüleiste für ein bestimmtes Fenster zu erstellen, legen Sie eine neue Instanz der Klasse MenuBar an:

MenuBar mb = new MenuBar();

Um diese Menüleiste als Standardmenü für das Fenster zu definieren, wenden Sie die setMenuBar()-Methode auf das Fenster an:

window.setMenuBar (mb);

Dann können Sie einzelne Menüs (Datei, Bearbeiten usw.) in die Menüleiste einfügen:

Menu m = new Menu("File");


mb.add(m);

Bei einigen Systemen kann ein spezielles Hilfemenü definiert werden, das auf der rechten Seite der Menüleiste ausgegeben wird. Sie können mit der setHelpMenu()-Methode ein bestimmtes Menü als Hilfemenü definieren:

Menu hm = new Menu("Help");

mb.add(hm);

mb.setHelpMenu(hm);

Falls Sie den Benutzer aus irgendeinem Grund daran hindern möchten, ein bestimmtes Menü auszuwählen, können Sie den disable()-Befehl auf das Menü anwenden (mit dem enable()-Befehl können Sie es wieder verfügbar machen):

m.disable();

Menüoptionen

Wir unterscheiden zwischen vier Optionsarten, die in einzelne Menüs eingefügt werden können:

Reguläre Menüoptionen können mit der MenuItem-Klasse eingefügt werden. Sie wenden dafür die add()-Methode an:

Menu m = new Menu("Tools");

m.add(new MenuItem("Info"));

m.add(new MenuItem("Colors"));

m.add(new MenuItem("Sizes"));

Untermenüs können einfach hinzugefügt werden, indem Sie eine neue Instanz von Menu erstellen und sie in das erste Menü einfügen. Dann fügen Sie Optionen in dieses Menü ein:

Menu sb = new Menu("Sizes");

m.add(sb);

sb.add(new MenuItem("Small"));

sb.add(new MenuItem("Medium2));

sb.add(new MenuItem("Large2));

Die CheckBoxMenuItem-Klasse erzeugt eine Menüoption mit einem Kontrollfeld, durch das die Option ein- und ausgeschaltet werden kann (durch Anklicken wird die Option ausgewählt, und erneutes Anklicken bewirkt, daß sie abgewählt wird). Sie erstellen eine Menüoption mit einem Kontrollfeld auf die gleiche Weise wie reguläre Menüoptionen:

CheckBoxMenuItem coords =

   new CheckboxMenuItem("Show Coordinates");

m.add(coords);

Schließlich können Sie eine Trennlinie in ein Menü einfügen, um Optionsgruppen zu trennen. Sie fügen dazu eine Menüoption mit dem Label »-« ein:

MenuItem msep = new MenuItem("-");

m.add(msep);

Mit der disable()-Methode können Sie jede Menüoption sperren und mit enable() wieder zur Verfügung stellen. Mit disable belegte Menüoptionen können nicht ausgewählt werden:

MenuItem mi = new MenuItem("Fill");

m.addItem(mi);

mi.disable();

Menüaktionen

Durch Auswahl einer Menüoption wird ein Aktionsereignis erzeugt. Sie können diese Aktion auf die gleiche Weise handhaben wie andere action-Methoden - durch Überschreiben von action(). Sowohl reguläre Menüoptionen als auch Menüoptionen mit Kontrollfeldern haben Aktionen, die ein zusätzliches Argument erzeugen, das die Beschriftung des jeweiligen Menüs darstellt. Sie können dieses Label verwenden, um zu bestimmten, welche Aktion stattfinden soll. Da CheckBoxMenuItem eine Subklasse von MenuItem ist, brauchen Sie diese Menüoption nicht als Sonderfall zu behandeln:

public boolean action(Event evt, Object arg) {

   if (evt.target instanceof MenuItem) {

      String label = (String)arg;

      if (label.equals("Show Coordinates")) toggleCoords();

      else if (label.equals("Fill")) fillcurrentArea();

      return true;

   }

   else return false;

}

Praktisches Beispiel

Wir fügen nun ein Menü in das Fenster ein, das Sie im vorherigen Abschnitt erstellt haben. Sie fügen es in die Constructor-Methode der MyFrame-Klasse ein (das Ergebnis sehen Sie in Abb. 14.2):

MyFrame(String title) {

   super(title);

   MenuBar mb = new MenuBar();

   Menu m = new Menu("Colors");

   m.add(new MenuItem("Red"));

   m.add(new MenuItem("Blue"));

   m.add(new MenuItem("Green"));

   m.add(new MenuItem("-"));

   m.add(new CheckBoxMenuItem("Reverse Text"));

   mb.add(m);

   mb.setHelpMenu(m);

   setMenuBar(mb);

...

}

Dieses Menü hat vier Optionen: Je eine für die Farben Rot, Blau und Grün (durch die je nach Auswahl der Hintergrund des Fensters geändert wird) und eine Menüoption mit einem Kontrollfeld zum Wechseln der Textfarbe (auf Weiß). Um diese Menüoptionen zu handhaben, brauchen Sie eine action()-Methode:

public boolean action(Event evt, Object arg) {

   if (evt.target instanceof MenuItem) {

      String label = (String)arg;

      if (label.equals("Red")) setBackground(Color.red);

      else if (label.equals("Blue")) setBackground(Color.blue);

      else if (label.equals("Green")) setBackground(Color.green);

      else if (label.equals("Reverse Text")) {

         if (getForeground() == Color.black)

            setForeground(Color.white);

         else setForeground(Color.black);

      }

      return true;

   }

   else return false;

}

Abbildung 14.2: Beispiel eines Menüs

Dialogfelder

Dialogfelder sind funktionell mit Rahmen vergleichbar, da sie neue Fenster am Bildschirm anzeigen. Im Gegensatz zu Fenstern sind Dialogfelder allerdings vorübergehender Natur. Sie werden beispielsweise benutzt, um Meldungen oder Warnungen auszugeben oder den Benutzer zu bestimmten Eingaben aufzufordern. Dialogfelder haben normalerweise keine Titelleiste (können aber eine haben) und weisen viele der allgemeinen Merkmale von Fenstern nicht auf. Außerdem können Sie mit fester Größe definiert werden oder modal sein.

Ein modales Dialogfeld verhindert die Eingabe in ein anderes am Bildschirm angezeigtes Fenster, so lange es geöffnet ist.

Das AWT bietet zwei Arten von Dialogfeldern: Die Dialog-Klasse enthält ein allgemeines Dialogfeld und FileDialog produziert ein plattformspezifisches Dialogfeld, um Dateien zum Speichern oder Öffnen auszuwählen.

Um ein allgemeines Dialogfeld zu erstellen, benutzen Sie einen dieser Constructors:

Da Sie dem Dialogfeld ein Frame-Argument verleihen müssen, können Sie Dialogfelder nur an Fenster anhängen, die bereits unabhängig vom Applet existieren.

Wie Rahmen sind auch Dialogfelder Panels, in denen Komponenten der Benutzeroberfläche angeordnet und Grafikoperationen ausgeführt werden können. Wie alle Fenster sind Dialogfelder zunächst unsichtbar. Sie können mit show() angezeigt und mit hide() verborgen werden.

Wir fügen jetzt in das Beispiel mit dem Popup-Fenster ein Dialogfeld ein. Sie schreiben eine Menüoption zum Ändern des Fenstertextes, wodurch das Dialogfeld Enter Text eingeblendet wird (siehe Abb. 14.3):

Abbildung 14.3: Das Dialogfeld Enter Text

Fügen Sie zuerst (in die Constructor-Methode der MyFrame-Klasse) eine Menüoption in dieses Fenster ein, um den Text des Popup-Fensters zu ändern:

m.add(new MenuItem("Set Text..."));

In der gleichen Methode können Sie das Dialogfeld erstellen und die Einzelteile auslegen (da das Dialogfeld zunächst unsichtbar ist, erscheint nichts am Bildschirm, was Sie jetzt einfügen, bis Sie show() definieren):

dl = new Dialog(this, "Enter Text",true);

dl.setLayout(new GridLayout(2,1,30,30));

tf = new TextField(l.getText(),20);

dl.add(tf);

dl.add(new Button("OK"));

dl.resize(150,75);

Durch die Aktion der Auswahl der gerade eingefügten Menüoption wird das Dialogfeld angezeigt. Durch Anklicken der OK-Schaltfläche wird es wieder ausgeblendet. Deshalb müssen Sie in die Aktionsmethode dieser Klasse Eigenschaften einfügen, damit das Dialogfeld richtig funktioniert. Schreiben Sie eine Zeile, um die neue Menüoption zu testen:

if (evt.target instanceof MenuItem) {

   if (label.equals("Red")) setBackground(Color.red);

   if (label.equals("Blue")) setBackground(Color.blue);

   if (label.equals("Green")) setBackground(Color.green);

   if (label.equals("Set Text...")) dl.show();

}

Da OK eine Schaltfläche ist, müssen Sie für diese Schaltfläche getrennt von den anderen Menüoptionen einen Sonderfall einfügen. In diesem Sonderfall setzen Sie den Text des Fensters auf den im Textfeld eingetippten Text, dann verbergen Sie das Dialogfeld wieder:

if (evt.target instanceof Button) {

   if (label.equals("OK")) {

      l.setText(tf.getText());

      dl.hide();

   }

}

Dateidialogfelder

FileDialog bietet grundlegende Dialogfelder zum Öffnen oder Speichern von Dateien, d. h. für den Zugriff auf das Dateisystem. Die FileDialog-Klasse ist systemunabhängig. Je nach Plattform wird jedoch das Standarddialogfeld »Datei öffnen« angezeigt.

Bei Applets kann das Dateidialogfeld zwar angezeigt, jedoch aufgrund von Sicherheitseinschränkungen nichts darin ausgeführt werden (das lokale System wird gesperrt, falls der Zugriff auf Dateien gelingt). FileDialog ist eigentlich nur in Java-Anwendungen sinnvoll.

Um ein Dateidialogfeld zu erstellen, benutzen Sie folgende Constructors:

Nachdem Sie eine FileDialog-Instanz erstellt haben, verwenden Sie show() zum Anzeigen:

FileDialog fd = new FileDialog(this, "FileDialog");

fd.show();

Wählt der Benutzer in diesem Dialogfeld eine Datei aus und gibt das Dialogfeld wieder frei, können Sie die gewählte Datei mit den Methoden getDirectory() und getFile() holen. Beide Methoden geben Zeichenketten aus, die die gewählte Datei bezeichnen. Sie können dann die Datei durch bestimmte Handhabungsmethoden (die Sie nächste Woche lernen) öffnen und diese Datei lesen oder beschreiben lassen.

Fensterereignisse

Gestern haben Sie gelernt, wie man Ereignismethoden schreibt, und festgestellt, daß die Event-Klasse viele Standardereignisse definiert. Fensterereignisse sind Teil dieser Liste, so daß einige davon in diesem Zusammenhang interessant sind. Tabelle 14.1 enthält eine Auswahl von Ereignissen aus der Event-Klasse.

Methode Aktion
WINDOW_DESTROY Wird erzeugt, wenn ein Fenster »vernichtet« wird (beispielsweise, wenn der Browser oder Appletviewer beendet wird).
WINDOW_EXPOSE Wird erzeugt, wenn das Fenster in den Vordergrund (vor andere Fenster) geholt wird.
WINDOW_ICONIFY Wird erzeugt, wenn das Fenster zum Symbol verkleinert wird.
WINDOW_DEICONIFY Wird erzeugt, wenn das Fenster vom Symbol auf Normalgröße wiederhergestellt wird.
WINDOW_MOVED Wird erzeugt, wenn das Fenster verschoben wird.
Tabelle 14.1: Fensterereignisse aus der Event-Klasse.

AWT-Fenster in Einzelanwendungen

Da Rahmen allgemeingültige Mechanismen zum Erstellen von AWT-Fenstern mit Panels sind, können Sie sie in Ihren einzelnen Java-Anwendungen verwenden und alle Applet-Fähigkeiten, die Sie diese Woche gelernt haben, mühelos nutzen. Hierfür schreiben Sie Ihre Anwendung wie ein Applet (mit Vererbung von der Applet-Klasse und unter Verwendung von Threads, Grafiken sowie Komponenten für die Benutzeroberfläche, falls erforderlich), dann fügen Sie eine main()-Methode ein. Hier ist ein Beispiel für eine Klasse namens MyAWTClass:

public static void main(String args[]) {

   Frame f = new Frame("My Window");

   MyAWTClass mac = new MyAWTClass();

   mac.init();

   mac.start();

   f.add("Center"), mac);

   f.resize(300, 300);

   f.show();

}

Diese main()-Methode bewirkt fünf Dinge:

Mit diesem Mechanismus können Sie ein Java-Programm entwickeln, das als Applet oder Anwendung gleich gut funktioniert. Sie fügen lediglich init() für Applets oder main() für Anwendungen ein.

Wenn Sie eine Anwendung entwickeln, die diesen Mechanismus nutzt, müssen Sie darauf achten, daß Ihre init()-Methoden Parameter von einer HTML-Datei holen. Wenn Sie ein Applet als Anwendung ausführen, brauchen Sie keine HTML-Parameter an die init()-Methode abzugeben. Sie geben sie statt dessen als Argumente in der Befehlszeile ein und handhaben sie in der main()-Methode. Dann setzen Sie ein Flag, um die init()-Methode am Lesen nicht existierender Parameter zu hindern.

Vernetzung in Java

Mit »Vernetzung« ist hier die Fähigkeit gemeint, zwischen einem Applet oder einer Anwendung zu einem System über ein Netz eine Verbindung herzustellen. Hierfür stehen in Java die Klassen des Pakets java.net zur Verfügung, die plattformübergreifende Abstraktionen für einfache Vernetzungsoperationen, z. B. das Verbinden und Abrufen von Dateien über übliche Web-Protokolle oder das Erstellen Unix-artiger Sockets, enthalten. In Verbindung mit Ein- und Ausgabeströmen (hierüber lernen Sie nächste Woche mehr) ist das Lesen und Schreiben von Dateien über ein Netz so einfach wie auf einem lokalen System.

Selbstverständlich gibt es gewisse Einschränkungen. Java-Applets können nicht auf der Platte der Gast-Maschine schreiben und lesen. Je nach Browser können Java-Applets eventuell nicht mit anderen Systemen, außer dem, auf dem sie ursprünglich gespeichert wurden, verbunden werden. Trotz dieser Einschränkungen können Sie aber viel erreichen und das Web umfassend nutzen, um Informationen über das Netz zu lesen und zu verarbeiten.

In diesem Abschnitt werden drei Arten erklärt, wie Sie mit Systemen im Netz kommunizieren können:

Verknüpfungen in Applets

Die wohl einfachste Art, in einem Applet Vernetzungen zu realisieren, ist die Anweisung des Browsers, der das Applet ausführt, eine neue Seite zu laden. Sie benutzen dies beispielsweise, um animierte Bild-Maps zu erstellen, die beim Anklikken eine neue Seite laden.

Um Ihr Applet mit einer neuen Seite zu verknüpfen, erstellen Sie eine neue Instanz der Klasse URL. Sie haben dies bereits im Zusammenhang mit Bildern gesehen. Hier steigen Sie aber tiefer in die Materie ein.

Die url-Klasse repräsentiert einen Uniform Resource Locator. Um einen neuen URL zu erstellen, können Sie eine von vier verschiedenen Formen verwenden:

Bei der letzten Form (Erstellen eines URL aus einer Zeichenkette) müssen Sie eine eventuell falsch gebildete URL-Adresse berücksichtigen, deshalb umgeben Sie den URL-Constructor mit try...catch:

String url = "http://www.yahoo.com/";

try { theURL = new URL(url); }

catch ( MalformedURLException e) {

   System.out.println("Bad URL: " + theURL);

}

Das Holen eines URL-Objekts ist der schwierige Teil. Wenn Sie eines haben, brauchen Sie es nur an den Browser weiterzugeben. Das geschieht mit einer einzigen Codezeile, wobei theURL das URL-Objekt ist, zu dem die Verknüpfung hergestellt werden soll:

getAppletContext().showDocument(theURL);

Der Browser, der Ihren URL enthält, wird dann geladen und zeigt das entsprechende Dokument an.

Listing 14.2 enthält den Code für ein einfaches Applet, das drei Schaltflächen anzeigt, die wichtige Web-Standorte darstellen (Sie sehen die Schaltflächen in Abb. 14.4). Durch Anklicken einer Schaltfläche wird das durch Sie bezeichnete Dokument geladen.

Listing 14.2: Die Bookmark-Schaltflächen

import java.awt.*;

import java.net.URL;

import java.net.MalformedURLException;



public class ButtonLink extends java.applet.Applet {



   Bookmark bmlist[] = new Bookmark[3];



   public void init() {

      bmlist[0] = new Bookmark("Laura's Home Page",

         "http://www.lne.com/lemay/");

      bmlist[1] = new Bookmark("Yahoo",

         "http://www.yahoo.com");

      bmlist[2] = new Bookmark("Java Home Page",

         "http://java.sun.com");



      setLayout(new GridLayout(bmlist.length,1,10,10));

      for (int i = 0; i < bmlist.length; i++) {

         add(new Button(bmlist[i].name));

      }

   }

   public boolean action(Event evt, Object arg) {

      if (evt.target instanceof Button) {

         LinkTo(String)arg);

         return true;

      }

   else return false;

   }

   void LinkTo(String name) {

      URL theURL = null;

      for (int i = 0; i < bmlist.length; i++) {

         if (name.equals(bmlist[i].name))

            theURL = bmlist[i].url;

      }

      if (theURL != null)

         getAppletContext().showDocument(theURL);

   }

}

class Bookmark {

   String name;

   URL url;



   Bookmark(String name, String theURL) {

      this.name = name;

      try { this.url = new URL(theURL); }

      catch ( MalformedURLException e) {

         System.out.println("Bad URL: " + theURL);

      }

   }

}

Abbildung 14.4: Die Bookmark-Schaltflächen

Dieses Applet besteht aus zwei Klassen: Die erste implementiert das Applet, die zweite ist eine Klasse, die ein Bookmark (Lesezeichen) darstellt. Bookmarks bestehen wiederum aus zwei Teilen: einem Namen und einem URL.

Dieses Applet erstellt drei Bookmark-Instanzen und speichert sie in einem Bookmark-Array (dieses Applet könnte leicht so abgeändert werden, daß es Bookmarks als Parameter aus einer HTML-Datei enthält). Für jedes Bookmark wird eine Schaltfläche erstellt, deren Beschriftung dem Wert des Bookmark-Namens entspricht.

Durch Anklicken einer Schaltfläche wird die LinkTo()-Methode aufgerufen, die den Browser anweist, den URL zu laden, der auf dieses Bookmark verweist.

Öffnen von Web-Verbindungen

Anstatt den Browser lediglich aufzufordern, den Inhalt einer Datei zu laden, möchten Sie vielleicht den Inhalt einer Datei in Ihrem Applet benutzen. Ist die betreffende Datei im Web gespeichert und über die üblichen URL-Formen (http, ftp usw.) zugänglich, können Sie die url-Klasse benutzen, um die Datei in Ihrem Applet zu verwenden.

Aus Sicherheitsgründen können Applets nur rückwärts mit dem gleichen Host, von dem sie ursprünglich geladen wurden, verbunden werden. Das bedeutet beispielsweise bei einem Applet, das auf einem System namens www.myhost.com gespeichert ist, daß Ihr Applet nur mit diesem Host (und dem gleichen Hostnamen, deshalb vorsichtig mit Aliasnamen!) eine Verbindung herstellen kann. Befindet sich die Datei, die das Applet abrufen möchte, auf dem gleichen System, sind URL-Verbindungen eine einfachere Möglichkeit, dies zu erreichen.

openStream()

URL definiert eine Methode namens openStream(), die eine Netzverbindung mit einem bestimmten URL öffnet und eine Instanz der Klasse InputStream (Teil des java.io-Pakets) ausgibt. Wenn Sie diesen Strom in einen DataInputStream (mit einem BufferedInputStream in der Mitte, um die Leistung zu steigern) konvertieren, können Sie Zeichen und Zeilen aus diesem Strom lesen (Sie lernen alles über Ströme am 19. Tag). Diese Zeilen öffnen beispielsweise eine Verbindung zu dem URL, der in der Variablen theURL gespeichert ist, lesen den Inhalt der Datei und geben ihn auf dem Standardausgabegerät aus:

try {

   InputStream in = theURL.openStream();

   DataInputStream data = new DataInputStream(

      new BufferedInputStream(in);

   String line;

   while ((line = data.readLine()) != null) {

      System.out.println("line");

   }

}

catch (IOException e) {

   System.out.println("IO Error: " + e.getMessage());

}

Sie müssen alle Zeilen zwischen eine try...catch-Anweisung setzen, um IOException-Ausnahmen zu berücksichtigen.

Das folgende Beispiel eines Applets nutzt die openStream()-Methode, um eine Verbindung zu einem Web-Standort herzustellen. Dann wird über diese Verbindung eine Datei (»Der Rabe« von Edgar Allen Poe) gelesen und in einem Textbereich angezeigt. Listing 14.3 enthält den vollständigen Code für dieses Applet. Das Ergebnis nach dem Lesen der Datei sehen Sie in Abb. 14.5.

Listing 14.3: Die GetRaven-Klasse

1:   import java.awt.*;

2:   import java.io.DataInputStream;

3:   import java.io.BufferedInputStream;

4:   import java.io.IOException;

5:   import java.net.URL;

6:   import java.net.URLConnection;

7:   import java.net.MalformedURLException;

8:

9:   public class GetRaven extends java.applet.Applet

10:      implements Runnable {

11:

12:      URL theURL;

13:      Thread runner;

14:      TextArea ta = new TextArea("Getting text...",30,70);

15:

16:      public void init() {

17:

18:         String url = "http://www.lne.com/Web/Java/raven.txt";

19:         try { this.theURL = new URL(url); }

20:         catch ( MalformedURLException e) {

21:            System.out.println("Bad URL: " + theURL);

22:      }

23:      add(ta);

24:   }

25:

26:   public Insets insets() {

27:      return new Insets(10,10,10,10);

28:   }

29:

30:   public void start() {

31:      if (runner == null) {

32:         runner = new Thread(this);

33:         runner.start();

34:      }

35:   }

36:

37:   public void stop() {

38:      if (runner != null) {

39:         runner.stop();

40:         runner = null;

41:      }

42:   }

43:

44:   public void run() {

45:      InputStream conn = null;

46:      DataInputStream data = null;

47:      String line;

48:      StringBuffer buf = new StringBuffer();

49:

50:      try {

51:         conn = this.theURL.openStream();

52:         data = new DataInputStream(new BufferedInputStream(

53:            conn));

54:

55:         while ((line = data.readLine()) != null) {

56:            buf.append(line + "\n");

57:         }

58:

59:         ta.setText(buf.toString());

60:         }

61:         catch (IOException e) {

62:            System.out.println("IO Error:" + e.getMessage());

63:         }

64:      }

65:   }

Abbildung 14.5: Die GetRaven-Klasse

Die init()-Methode (Zeilen 16 bis 24) richtet den URL und den Textbereich ein, in dem diese Datei angezeigt wird. Der URL könnte leicht über einen HTML-Parameter an das Applet abgegeben werden. Hier wurde er der Einfachheit halber hartcodiert.

Da es einige Zeit dauern kann, bis die Datei über das Netz geladen wird, stellen Sie diese Routine in einen eigenen Thread und benutzen die Ihnen inzwischen bestens bekannten Methoden start(), stop() und run(), um diesen Thread zu steuern.

Innerhalb von run() (Zeilen 44 bis 64) findet die eigentliche Arbeit statt. Hier initialisieren Sie mehrere Variablen und öffnen die Verbindung zum URL (mit der openStream()-Methode in Zeile 51). Ist die Verbindung aufgebaut, richten Sie in den Zeilen 52 bis 56 einen Eingabestrom ein, von dem zeilenweise gelesen wird. Das Ergebnis wird in eine Instanz von StringBuffer (das ist eine änderbare Zeichenkette) gestellt.

Nachdem alle Daten gelesen wurden, konvertiert Zeile 59 das StringBuffer-Objekt in eine echte Zeichenkette und stellt das Ergebnis in den Textbereich.

In diesem Beispiel wurde der Teil des Codes, der eine Netzverbindung herstellt, von der Datei liest und eine Zeichenkette erstellt, zwischen eine try...catch-Anweisung gestellt. Tritt während des Versuchs, die Datei zu lesen oder zu verarbeiten, ein Fehler auf, ermöglicht diese Anweisung die Wiederherstellung, ohne daß das gesamte Programm abstürzt (in diesem Fall beendet das Programm mit einem Fehler, weil ansonsten wenig getan werden kann, wenn das Applet die Datei nicht lesen kann). Mit try und catch können Sie Ihr Applet aus einer Fehlersituation befreien. Am 18. Tag lernen Sie alles über Ausnahmen.

Die URLconnection-Klasse

Die openStream()-Methode von URL ist eigentlich eine vereinfachte Ausgabe der URLconnection-Klasse. URLconnection bietet eine Möglichkeit, Dateien anhand von URLs, beispielsweise von Web- oder FTP-Standorten, abzurufen. URLconnection ermöglicht Ihnen auch, Ausgabeströme zu erstellen, sofern das Protokoll dies gestattet.

Um eine URL-Verbindung zu nutzen, erstellen Sie zuerst eine neue Instanz der Klasse URLconnection, richten die Parameter ein (beispielsweise, ob sie schreiben kann) und benutzen dann die connect()-Methode, um die Verbindung aufzubauen. Beachten Sie, daß die Klasse bei einer URL-Verbindung das Protokoll in bezug auf den ersten URL-Teil handhabt, deshalb brauchen Sie den Abruf einer Datei nicht spezifisch anfordern. Sie muß lediglich gelesen werden.

Sockets

Für vernetzte Anwendungen, die über das hinausgehen, was die Klassen URL und URLconnection bieten (z. B. für andere Protokolle oder allgemeine vernetzte Anwendungen) bietet Java die Klassen Socket und ServerSocket als Abstraktion von Socket-Programmiertechniken.

Eine umfassende Erklärung der Socket-Programmierung würde den Umfang dieses Buches sprengen. Falls Sie noch nie mit Sockets gearbeitet haben, versuchen Sie, ob Sie mit openStream() die gewünschten Ergebnisse erzielen. Falls das Ihren Ansprüchen nicht genügt, finden Sie in Büchern, die sich speziell mit der Socket-Programmierung befassen, das nötige Hintergrundwissen, das Sie auch auf Java-Sockets anwenden können.

Die Socket-Klasse bietet eine clientseitige Socket-Schnittstelle, die mit Unix-Standard-Sockets vergleichbar ist. Um eine Verbindung herzustellen, legen Sie eine neue Instanz von Socket an (wobei hostname der Host ist, zu dem die Verbindung herzustellen ist, und portnum die Portnummer ist):

Socket connection = new Socket(hostname, portnum);

Auch wenn Sie Sockets in einem Applet verwenden, unterliegen Ihre Applets nach wie vor den Sicherheitseinschränkungen in bezug auf Verbindungen.

Nachdem Sie den Socket geöffnet haben, können Sie Ein- und Ausgabeströme verwenden, um über diesen Socket zu lesen und zu schreiben (Sie lernen Ein- und Ausgabeströme am 19. Tag):

DataInputStream in = new DataInputStream(

   new BufferedInputStream(connection.getInputStream()));

DataOutputStream out = new DataOutputStream(

   new BufferedOutputStream(connection.getOutputStream()));

Zum Schluß müssen Sie den Socket schließen (dadurch werden auch alle Ein- und Ausgabeströme geschlossen, die Sie für diesen Socket eingerichtet haben):

connection.close();

Serverseitige Sockets funktionieren auf ähnliche Weise, mit Ausnahme der accept()-Methode. Ein Server-Socket richtet sich nach einem TCP-Port, um eine Client-Verbindung aufzubauen. Wenn sich ein Client an diesen Port anschließt, akzeptiert die accept()-Methode eine Verbindung von diesem Client. Durch Verwendung von Client- und Server-Sockets können Sie Anwendungen entwikkeln, die miteinander über das Netz kommunizieren.

Um einen Server-Socket zu erstellen und an einen Port zu binden, legen Sie eine neue Instanz von ServerSocket mit der Portnummer an:

ServerSocket sconnection = new ServerSocket(8888);

Um diesen Port zu bedienen (und bei Anfrage eine Verbindung von Clients entgegenzunehmen), benutzen Sie die accept()-Methode:

sconnection.accept();

Nach dem Aufbau der Socket-Verbindung können Sie Ein- und Ausgabeströme verwenden, um vom Client zu lesen und zu schreiben.

Weitere Informationen über Java-Sockets finden Sie im Paket java.net.

Verschiedene Applet-Tips

Die letzte Lektion der zweiten Woche beende ich mit ein paar kleinen Tips, die sonst nirgends hineinpassen: Die Verwendung von showStatus(), um Meldungen im Browser-Statusfenster auszugeben, Applet-Informationen bereitzustellen und zwischen mehreren Applets auf der gleichen Seite eine Kommunikation zu ermöglichen.

Die showStatus-Methode

Die showStatus()-Methode ist in der Applet-Klasse verfügbar und ermöglicht Ihnen, eine Zeichenkette in der Statuszeile des Browsers, in dem das Applet ausgegeben wird, anzuzeigen. Sie können dies zum Ausgeben von Status-, Fehler- oder sonstigen Meldungen benutzen:

getAppletContext().showStatus("Change the color");

Mit der getAppletContext()-Methode erhält Ihr Applet Zugang zu Funktionen des Browsers. Sie haben dies teilweise schon im Zusammenhang mit Verknüpfungen, für die Sie die showDocument()-Methode benutzt haben, um den Browser zum Laden einer Seite aufzufordern, kennengelernt. showStatus() nutzt den gleichen Mechanismus, um Statusmeldungen auszugeben.

showStatus() wird eventuell nicht in allen Browsern unterstützt, deshalb verlassen Sie sich in bezug auf die volle Funktionalität Ihres Applets nicht auf den Browser. Die Methode bietet eine nützliche Art der Kommunikation mit dem Benutzer. Wenn Sie eine zuverlässigere Methode benötigen, richten Sie in Ihrem Applet ein Label ein und aktualisieren Sie es auf die Meldungsänderungen.

Applet-Informationen

Das AWT-Toolkit bietet einen Mechanismus zum Einbinden von Informationen in Ihr Applet. Normalerweise umfaßt der Browser, in dem das Applet betrachtet wird, eine Möglichkeit, Informationen anzuzeigen. Sie können diesen Mechanismus anwenden, um beispielsweise Ihr Applet mit Ihrem Namen oder Ihrer Firma zu unterzeichnen oder Kontaktinformationen auszugeben, damit die Benutzer auf Wunsch mit Ihnen in Verbindung treten können.

Um Informationen über Ihr Applet bereitzustellen, überschreiben Sie die getAppletInfo()-Methode:

public String getAppletInfo() {

   return "GetRaven copyright 1995 Laura Lemay";

}

Kommunikation zwischen Applets

Zuweilen möchten Sie vielleicht mehrere Applets in eine HTML-Seite stellen. Um das zu realisieren, können Sie mehrere verschiedene Wiederholungen des Applet-Tags einbinden. Der Browser erstellt dann verschiedene Instanzen für jedes Applet, das auf der HTML-Seite erscheint.

Was nun, wenn diese Applets miteinander kommunizieren sollen? Oder wenn in einem Applet etwas geändert wird, das die übrigen Applets in irgendeiner Weise betrifft?

Die beste Möglichkeit hierfür ist die Verwendung des Applet-Kontextes, um mehrere Applets in eine Seite einzubinden. Den Umgang mit der getAppletContext()-Methode haben Sie bereits in verschiedenen Beispielen gelernt. Sie können diese Methode auch anwenden, um weitere Applets in eine Seite zu stellen. Um beispielsweise eine Methode in allen Applets auf einer Seite (einschließlich des jeweils aktuellen Applets) aufzurufen, verwenden Sie die getApplets()-Methode und eine for-Schleife. Das sieht so aus:

for (Enumeration e = getAppletContext().getApplets();

   e.hasMoreElements();) {

   Applet current = (Applet) (e.nextElement());

   sendMessage(current);

}

Die getApplets()-Methode gibt ein Enumeration-Objekt mit einer Liste der auf der Seite befindlichen Applets aus. Diese Wiederholung des Enumeration-Objekts ermöglicht Ihnen den Zugriff auf alle Elemente nacheinander in Enumeration.

Etwas komplizierter wird es, wenn Sie eine Methode in einem spezifischen Applet aufrufen wollen. Hierfür geben Sie jedem Applet einen Namen und setzen in den Körper des betreffenden Applet-Codes eine Referenz auf diesen Namen.

Um ein Applet zu benennen, verwenden Sie den NAME-Parameter in Ihrer HTML-Datei:

<P>This applet sends information:

<APPLET CODE="MyApplet.class" WIDTH=100 HEIGHT=150

   NAME="sender"> </APPLET>

<P>This applet receives information from the sender:

<APPLET CODE="MyApplet.class" WIDTH=100 HEIGHT=150

   NAME="receiver"> </APPLET>

Für eine Referenz auf ein anderes Applet auf der gleichen Seite verwenden Sie die getApplet()-Methode aus dem Applet-Kontext mit dem Namen des betreffenden Applets. Dadurch erhalten Sie eine Referenz auf das Applet dieses Namens. Sie können dann auf das Applet so verweisen, als wäre es ein Objekt: Methoden aufrufen, seine Instanzvariablen setzen usw.:

// Empfänger-Applet aufrufen

Applet receiver = getAppletContext().getApplet("receiver");

// Das Applet anweisen, sich zu aktualisieren

receiver.update(text, value);

In diesem Beispiel wird die getApplet()-Methode verwendet, um eine Referenz auf das Applet mit dem Namen receiver zu erhalten. Mit dieser Referenz können dann Methoden in dem Applet aufgerufen werden, als wäre sie andere Objekte. Sie können beispielsweise receiver auffordern, sich auf die Informationen des aktuellen Applets fortzuschreiben, wenn beide Applets eine update()-Methode enthalten.

Durch Benennen Ihrer Applets und Einrichten darauf verweisender Referenzen anhand der in diesem Abschnitt beschriebenen Methoden können Ihre Applets miteinander kommunizieren und sich auf die jeweils geänderten Informationen des anderen Applets aktualisieren, so daß alle Applets auf einer Seite ein einheitliches Verhalten aufweisen.

Zusammenfassung

Herzlichen Glückwunsch! Atmen Sie tief durch - Sie haben die zweite Woche hinter sich gebracht. Diese Woche war angereichert mit nützlichen Informationen über das Erstellen von Applets und die Verwendung der AWT-Klassen von Java, um Applets mit ausgereiften Schnittstellen zu zeichnen, anzuzeigen, zu animieren und Eingaben zu verarbeiten.

Mit der heutigen Lektion und dem Erlernen von drei Konzepten haben Sie die Einführung in die Grundlagen von Applets und des AWT-Toolkits beendet.

Erstens haben Sie gelernt, mit Fenstern, Rahmen, Menüs und Dialogfeldern zu arbeiten, um ein Rahmenwerk für Ihre Applets zu erstellen oder die Applet-Merkmale in Java-Anwendungen voll zu nutzen.

Zweitens haben Sie die Grundlagen der Java-Vernetzung anhand einiger Klassen aus dem Paket java.net gelernt. Applet-Vernetzung beinhaltet einfache Aspekte wie das Zeigen des Browsers auf eine andere Seite in Ihrem Applet, aber auch komplexere Aufgaben wie das Abrufen von Dateien vom Web über Web-Standardprotokolle (http, ftp usw.). Für anspruchsvolle Vernetzungslösungen bietet Java Socket-Schnittstellen, mit denen viele netzorientierte Applets entwickelt werden können, z. B. Client-Server-Interaktionen, Chat-Sitzungen usw.

Drittens haben Sie einige nützliche Zusätze gelernt - kleine Merkmale des AWT-Toolkits für Applets, darunter showStatus(), um Informationen über Ihr Applet auszugeben, und die Kommunikation zwischen mehreren Applets auf einer Seite.


Fragen und Antworten

F: Alle Popup-Fenster, die ich mit dem Appletviewer erstelle, werden mit einer großen roten Leiste und dem Text Warning: applet window angezeigt. Was bedeutet das?

A: Durch die Warnung sollen Sie (und die Benutzer des Applets) darauf aufmerksam gemacht werden, daß das angezeigte Fenster von einem Applet, nicht vom Browser erzeugt wurde. Das ist eine Sicherheitsmaßnahme, um Applet-Programmierer daran zu hindern, ein Fenster anzuzeigen, das sich als Browser-Fenster ausgibt und beispielsweise den Benutzer nach seinem Paßwort fragt.

Es gibt keine Möglichkeit, diese Warnung zu verbergen oder anderweitig auszublenden.

F: Wozu soll ein Dateidialogfeld gut sein, wenn damit keine Dateien im lokalen Dateisystem gelesen oder geschrieben werden können?

A: Applets können grundsätzlich auf einem lokalen Dateisystem weder lesen noch schreiben. Da Sie aber AWT-Komponenten in Applets und Java-Anwendungen verwenden können, ist das Dateidialogfeld für diesen Zweck sehr nützlich.

F: Wie kann ich eine HTML-Formulareinreichung in einem Java-Applet simulieren?

A: Derzeit ist das in Applets schwierig. Die beste (und einfachste) Möglichkeit ist die Verwendung der GET-Notation, um den Browser zu veranlassen, den Formularinhalt für Sie einzureichen.

HTML-Formulare können auf zwei Arten eingereicht werden: Durch Verwendung der GET-Anfrage oder mit POST. Wenn Sie GET verwenden, werden die Informationen Ihres Formulars im URL codiert. Das kann etwa so aussehen:

http://www.blah.com/cgi-bin/myscript?foo=1&bar=2&name=Laura

Da das Formular im URL codiert ist, können Sie ein Java-Applet schreiben, das ein Formular simuliert, Eingaben vom Benutzer anfordern und dann ein neues URL-Objekt mit den Formulardaten erstellen. Dann geben Sie diesen URL mit getAppletContext().showDocument() an den Browser weiter. Der Browser reicht die Formularergebnisse selbst ein. Bei einfachen Formularen genügt das.

F: Wie kann ich POST für Formulareinreichungen realisieren?

A: Sie müssen das simulieren, was ein Browser macht, um Formulare mit POST übersenden zu können: Öffnen Sie einen Socket zum Server und übersenden Sie die Daten. Das sieht etwa so aus (das genaue Format wird vom HTTP-Protokoll bestimmt):

POST /cgi-bin/mailto.cgi HTTP/1.0
Content-type: application/x-www-form-urlencoded
Content-length: 36
{hier stehen Ihre codierten Formulardaten}

Wenn Sie alles richtig gemacht haben, erhalten Sie die CGI-Formularausgabe vom Server zurück. Dann liegt es an Ihrem Applet, diese Ausgabe korrekt zu verarbeiten. Im Fall einer Ausgabe in HTML besteht eigentlich keine Möglichkeit, diese Ausgabe an den Browser, in dem Ihr Applet ausgeführt wird, weiterzugeben. Falls Sie einen URL zurückerhalten, können Sie den Browser auf diesen URL umleiten.

F: showStatus funktioniert nicht in meinem Browser. Wie kann ich meinen Lesern Statusinformationen ausgeben?

A: Wie Sie in dem Abschnitt über showStatus() gelernt haben, liegt es absolut am Browser, ob er showStatus() unterstützt. Wenn Sie in Ihrem Applet ein statusähnliches Verhalten benötigen, können Sie eine Statusbeschriftung (Label) im Applet erstellen, die auf die auszugebenden Informationen aktualisiert wird.


Copyright ©1996 Markt&Technik
Buch- und Software- Verlag GmbH
Alle Rechte vorbehalten. All rights reserved.

Schreiben Sie uns!

Previous Page TOC Index Next Page See Page