Weitere aktuelle Java-Titel finden Sie bei dpunkt.
 Inhaltsverzeichnis   Auf Ebene Zurück   Seite Zurück   Seite Vor   Auf Ebene Vor   Eine Ebene höher   Index


7.4

Applets mit Applikationen vereinigt


Generell ist es nicht erforderlich, Applets von Applikationen zu trennen. Ein Applet kann gleichzeitig eine Applikation sein und umgekehrt. Die Unterscheidung ist lediglich von den Methoden abhängig, die implementiert werden, und von der Klasse, von der die Hauptklasse abgeleitet wird. Wenn die Anforderungen eines Applets und einer Applikation erfüllt sind, kann man das Programm sowohl in einem Browser als auch von der Konsole aus starten.

Hierzu muss das Programm Die Parameter, die ein Applet von der HTML-Seite erhält, können bei einer Applikation durch die Kommandozeile übergeben werden, um auch eine einheitliche Schnittstelle des Programms nach außen zu definieren. Der Parameterzugriff bei Applikationen erfolgt bei dieser Vorgehensweise über den Parameter von main(), bei Applets hingegen über die Methode getParameter().

Folgendes Programm ist wohl eine der einfachsten Formen einer Applikation, die auch als Applet gestartet werden kann:
  import java.applet.Applet;
  
  public class AppletApplicationDemo extends Applet {
  
    // Aufruf beim Start als Applikation
    public static void main(String args[]) {
      // Zuerst wird eine Instanz der Klasse angelegt
      // und anschließend der Name der Programm-Art ausgegeben.
      AppletApplicationDemo universalprogram =
                                  new AppletApplicationDemo();
      universalprogram.whoamI("applicaton");
    }
  
    // Aufruf beim Start als Applet
    public void init() {
      // Hier ist ein direkter Aufruf von 'whoamI' möglich
      whoamI("applet");
    }
  
    public void whoamI(String program){
      // Ausgabe der Programm-Art
      System.out.println("You've startet an "+program);
    }
  
  }
Startet man das Programm von der Konsole aus, wird in main() ein Exemplar der Hauptklasse erzeugt. Der Verweis auf das Exemplar befindet sich innerhalb von main(). Somit kann über dieses Exemplar auf die Methoden und Datenelemente der Klasse, in der sich main() befindet, zugegriffen werden.

Ist das Exemplar erzeugt, wird whoamI() mit dem Argument application aufgerufen. Dort wird der Text auf der Standardausgabe angezeigt. Der Umweg über das Exemplar ist notwendig, um whoamI() nicht static definieren zu müssen.

Beim Start als Applet ist der Ablauf analog. In diesem Fall muss jedoch nicht erst ein Exemplar der eigenen Klasse angelegt werden, und whoamI() wird der Text applet übergeben. Auf diese Weise ist gewährleistet, dass man anhand des ausgegebenen Textes immer sagen kann, wie das Programm gestartet wurde. In diesem Fall übernimmt init() die Rolle, die main() in einer Applikation besitzt.

Für ein Applet wird durch die Attribute WIDTH und HEIGHT Platz auf der HTML-Seite reserviert, der als Grundlage zum Informationsaustausch mit dem Benutzer dient. In diesem Platz können entweder Grafiken angezeigt oder eine grafische Benutzeroberfläche erzeugt werden.

Eine Applikation besitzt diese Funktionalität nicht. Um dennoch eine gemeinsame Schnittstelle zwischen einem Applet und einer Applikation zu schaffen, die grafische Elemente enthält, kann man die zu zeichnenden oder anzuzeigenden Elemente in einem Fenster darstellen, wenn das Programm als Applikation gestartet wird.

Möchte man Anwendungen mit grafischen Oberflächen entwickeln, die sowohl als Applet als auch als Applikation gestartet werden können, sollte man zusätzlich ein paar Dinge beachten. Im Folgenden wird dem Kapitel 8 etwas vorgegriffen und lediglich kurz auf die Unterschiede zwischen Applets und Applikationen mit grafischer Oberfläche eingegangen.

Beim Start der Anwendung als Applikation werden die Oberflächenelemente in einem Frame untergebracht. Beim Start als Applet wird die grafische Oberfläche direkt innerhalb des Applets im Browser aufgebaut.

Folgendes Programm ist eine einfache Anwendung mit grafischer Oberfläche, die sowohl als Applet als auch als Applikation ausgeführt werden kann:
  import java.applet.Applet;
  import java.awt.*;
  
  public class AppletApplicationGUIDemo extends Applet {
  
    // Aufruf beim Start als Applikation
    public static void main(String args[]) {
      Frame f = new Frame("An universal program");
      //  Hinzufügen des Panels zum Frame
      f.add("Center",
            new ComponentPanel("I'm an application"));
      // Setzen der Größe und Anzeigen des Frames
      f.setSize(300, 200);
      f.show();
    }
  
    // Aufruf beim Start als Applet
    public void init() {
      // Festlegen der Größe
      setSize(300, 200);
      // Zufügen des Panels zum Applet
      setLayout(new BorderLayout());
      add("Center", new ComponentPanel("I'm an applet"));
    }
  
  }
  
  class ComponentPanel extends Panel {
  
    public ComponentPanel(String text) {
      // Hinzufügen von zwei Komponenten zum Panel
      setLayout(new BorderLayout());
      add("Center", new TextArea());
      add("South", new Label(text, Label.CENTER));
    }
  
  }
Das Besondere an diesem Programm ist, dass die Komponenten, die die Oberfläche bilden, nicht direkt dem Applet hinzugefügt werden, sondern einer zweiten, von Panel abgeleiteten Komponente. Wenn das Programm als Applet gestartet wird, ruft der Interpreter zuerst init() auf. Dort wird ein Exemplar des Panel mit den eingebetteten Komponenten erzeugt und dem Applet hinzugefügt:
  add("Center", new ComponentPanel("I'm an applet"));

Wird das Programm als Applikation gestartet, wird beim Start main() aufgerufen. Da beim Start als Applikation noch kein Container vorhanden ist, der Komponenten aufnehmen kann, muss dieser zuerst angelegt werden. In diesem Fall wird dazu ein Frame verwendet. Danach kann man das Panel, das die Komponenten enthält, dem Frame hinzufügen und anschließend mit show() anzeigen.

Die oben definierte Klasse ComponentPanel wird gemeinsam von Applet und Applikation benutzt. Sowohl beim Start als Applet als auch beim Start als Applikation wird dieselbe grafische Oberfläche angezeigt.

In diesem Beispiel ist das Panel mit den gemeinsamen Komponenten relativ einfach gestaltet. Es enthält lediglich eine leere TextArea und ein Label, das signalisiert, ob das Programm als Applet oder als Applikation gestartet wurde. Auf diese Weise kann man aber auch komplexere Oberflächen variabel halten.

Abbildung 7.6: Eine grafische Oberfläche als Applet und Applikation kombiniert
Abbildung 7.6Abbildung 7.6


Material zum Beispiel

Wie Abbildung 7.6 zeigt, muss man jedoch die unterschiedlichen Größen bei Applets und Applikationen berücksichtigen. Die Breite des Applets wurde mit 300 und die Höhe mit 200 Pixeln initialisiert. Dasselbe gilt für den Frame, der die Komponenten beim Start als Applikation aufnimmt.

Dennoch steht bei der Variante als Applikation weniger Platz auf der Oberfläche zur Verfügung. Das liegt daran, dass der Rahmen des Frames in der initialisierten Größe enthalten ist. Dadurch wird der Platz, der den Komponenten effektiv zur Verfügung steht, verringert.

Neben dem Anzeigen der grafischen Oberfläche gibt es noch weitere Unterschiede, zwischen einem Applet und einer Applikation zu beachten, so z. B. beim Laden von Bildern oder beim Zugriff auf Dateien.

Innerhalb eines Applets wird ein Bild über den Aufruf der Methode getImage() geladen. Bei einer Applikation kann diese Methode nicht verwendet werden, da getImage() von der Klasse Applet implementiert wird. Sie ruft die entsprechende Methode des Interface AppletContext auf, das wiederum vom Browser implementiert wird. Beim Start als Applikation ist diese Implementierung somit nicht vorhanden.

Deshalb müssen Applikationen auf die getImage()-Methode der Klasse Toolkit zurückgreifen. Das wird in Abschnitt 7.3.2 beschrieben.

Um diese Unterschiede zwischen Applets und Applikationen in einer Anwendung zu verbergen und ein universelles Programm zu entwickeln, bietet es sich an, eine Klasse zu erzeugen, die eine Schnittstelle für jene Methoden enthält, die bei Applets und Applikationen unterschiedlich sind. Die Definition kann entweder mit Hilfe einer abstrakten Klasse oder eines Java-Interface erfolgen.

Folgende Klasse definiert eine Schnittstelle für das Laden von Bildern:
public class ProgramFactory {
  public abstract Image getImage(String location);
}
Für ein Applet könnte die Implementierung dieses Interface folgendermaßen aussehen:
public class AppletFactory extends ProgramFactory {
  protected Applet applet;

  public AppletFactory(Applet applet) {
    this.applet = applet;
  }
  
  public Image getImage(String image) {
    return applet.getImage(applet.getCodebase(),image);
  }
}
Dasselbe Interface könnte man ebenfalls für eine Applikation implementieren:
public class ApplicationFactory extends ProgramFactory {

  public Image getImage(String image) {
    return Toolkit.getDefaultToolkit().getImage(image);
  }
}
Wird nun die Anwendung entweder als Applet oder als Applikation gestartet, so muss jeweils das richtige ProgramFactory-Objekt gesetzt werden. Dadurch, dass beide Factory-Objekte über dieselbe Schnittstelle verfügen, muss innerhalb des eigentlichen Programms keine Unterscheidung zwischen dem Start als Applet oder als Applikation getroffen werden:

Das Setzen des ImageFactory-Objekts erfolgt jeweils in init() bzw. in main():
import java.applet.Applet;
import java.awt.*;

public class AppletApplicationGUIDemo extends Applet {

  // Aufruf beim Start als Applikation
  public static void main(String args[]) {
    Frame f = new Frame("An universal program");
    //  Hinzufügen des Panels zum Frame
    f.add("Center", 
        new ComponentPanel(new ApplicationFactory()));
    // Setzen der Größe und Anzeigen des Frames
    f.setSize(300, 200); 
    f.show();          
  }

  // Aufruf beim Start als Applet
  public void init() {
    // Festlegen der Größse
    setSize(300, 200);  
    // Hinzufügen des Panels zum Applet
    setLayout(new BorderLayout());
    add("Center", 
        new ComponentPanel(new AppletFactory(this)));
  }
}

class ImagePanel extends Panel {
  ImageFactory factory;
  Image img;

  public ComponentPanel(ProgramFactory factory) {
    // Speichern des Factory-Objektes
    this.factory = factory;
    img = factory.getImage("test.gif");
  }

  public void paint(Graphics g) {
    g.drawImage(img,0,0,this);
  }
}
Es ist allerdings zu beachten, dass diese Technik nur funktioniert, wenn das Bild immer relativ zur Hauptklasse des Applets definiert wird. Sobald Bilder mit absolutem Pfad angegeben werden, ist der Zugriff bei Applets wiederum anders als bei Applikationen.


 Inhaltsverzeichnis   Auf Ebene Zurück   Seite Zurück   Seite Vor   Auf Ebene Vor   Eine Ebene höher   Index

Copyright © 2002 dpunkt.Verlag, Heidelberg. Alle Rechte vorbehalten.