Java Micro: Displayprogrammierung

Aus Wikibooks

Wechseln zu: Navigation, Suche

In J2ME können zwei prinzipielle Wege unterschieden werden, wie eine Oberfläche programmiert werden kann: Die High-Level-API und die Low-Level-API. Für die erste Variante stehen bereits eine Reihe von Klassen bereit, mit denen schnell eine Anwendung erstellt werden kann. Programmierer haben allerdings kaum die Möglichkeit, das tatsächliche Erscheinungsbild auf dem Handy zu beeinflussen. Das bleibt der jeweiligen Implementierung von J2ME auf dem Handy überlassen. Für einfache Anwendungen, die nicht im Bereich Spiele liegen, ist zu empfehlen, die High-Level-API zu benutzen. Der Vorteil der recht einfachen Programmierung wird mit dem Nachteil erkauft, dass man nicht vorhersagen kann, wie die eigene Anwendung auf den unterschiedlichen Geräten aussieht.

Will man hingegen Anwendungen schreiben, die auf allen Handys gleich aussehen, so muss man die Low-Level-API benutzen, siehe folgendes Kapitel.

Das Konzept der High-Level-API ist nicht sehr komplex. Es gilt das Zusammenspiel von MIDlet, Display, Displayables und den Commands zu verstehen. Ein erster grober Überblick soll im folgenden gezeichnet werden.

Will ein MIDlet etwas auf dem Bildschirm des Handys darstellen, muss es auf den Display zugreifen. Display ist eine J2ME-Klasse aus dem Package javax.microedition.lcdui. Dieses Display kapselt, nach guter objektorientierter Manier die tatsächliche Hardware des Handys. Jedes MIDlet hat Zugriff auf genau ein Display. Es kann eine Referenz auf das Singelton Display durch folgenden Aufruf beziehen:

Display myDisplay = Display.getDisplay(this);

Ein Display ist in der Lage Displayables, also anzeigbare Dinge, zu präsentieren. Displayable ist ein Interface ebenfalls aus dem lcdui-Package. Es gibt eine ganze Reihe von Displayables, siehe Klassendiagramm (Bild folgt). Für die High-Level-Programmierung sind vor allem die Screens relevant und hier vor allem die vier Subklassen Form, TextBox, Alert und List. Anwendungen, die die High-Level-API nutzen setzen sich im Wesentlichen aus Objekten dieser vier Klassen zusammen. Auf sie wird im folgenden detailierter eingegangen werden. Zuvor soll allerdings noch beschrieben werden, wie Anwender mit einer Anwendung interagieren können.

Jedem Displayable können Kommandos (Objekte der Klasse Command) zugeordnet werden. Es gibt folgende Kommandotypen: - OK, EXIT, BACK, ITEM (ergänzen und erläutern!)

[Commands, CommandListener erklären]

Das folgende MIDlet soll das Vorgehen an einem kleinen Beispiel erläutern. Hier zunächst der Quelltext, im Anschluss folgen Erläuterungen:

 import javax.microedition.midlet.*;
 import javax.microedition.lcdui.*;

 public class MyMIDlet extends MIDlet implements CommandListener {
   
   private TextBox box1;
   private TextBox box2;
   
   private static final Command CMD_OK = new Command("OK", Command.OK, 0);
   private static final Command CMD_BACK = new Command("Back", Command.BACK, 0);
   private static final Command CMD_EXIT = new Command("Exit", Command.EXIT, 0);
   
   /** erzeugt die TextBox 1 einmalig. Bei jedem folgenden Aufruf
    * wird Referenz auf die fertige Box geliefert */
   private TextBox getBox1() {
       if( box1 == null ) {
           // Textbox erzeugen
           box1 = new TextBox("Box1-Titel", "initialer Text Box1", 100, TextField.ANY);
           box1.addCommand(CMD_OK);
           box1.addCommand(CMD_EXIT);
           box1.setCommandListener(this);
       }
       return box1;
   }
   
   private TextBox getBox2() {
       if( box2 == null ) {
           // Textbox erzeugen
           box2 = new TextBox("Box2-Titel", "initialer Text Box2", 100, TextField.ANY);
           box2.addCommand(CMD_BACK);
           box2.addCommand(CMD_EXIT);
           box2.setCommandListener(this);
       }
       return box2;
   }
   
   public void commandAction(Command cmd, Displayable dsp) {
       if(dsp == box1) {
           if( cmd == CMD_OK) {
               Display.getDisplay(this).setCurrent(getBox2());
           }
       } else if (dsp == box2) {
           if( cmd == CMD_BACK ) {
               Display.getDisplay(this).setCurrent(getBox1());
           }
       }
       
       if( cmd == CMD_EXIT ) {
           Display.getDisplay(this).setCurrent(null);
           destroyApp(false);
           notifyDestroyed();
       }
   }   
   
   public void startApp() {
       Display.getDisplay(this).setCurrent(getBox1());
   }
   
   public void pauseApp() {
   }
   
   public void destroyApp(boolean unconditional) {
   }
}

MyMidlet implementiert im obigen Beispiel selber das Interface CommandListener - ein, bei kleinen Programmen, gängige Vorgehen. Innerhalb der Klasse werden zunächst drei Commandos definiert, jeweils eins vom Typ OK, EXIT und BACK. Der Typ des Kommandos hat Einfluss auf die Darstellung auf dem Handy. Er hat keinen direkten Einfluss auf die Art der Bearbeitung.

Es folgen zwei Methoden getBox1 und getBox2. Beide Methoden erzeugen jeweils beim ersten Aufruf eine neue Textbox. Bei jedem weiteren Aufruf liefern sie die Referenz auf die zuvor erzeugte Textbox.

Die Erzeugung der Textbox erfolgt einfach durch den Aufruf von

 new TextBox("Box1-Titel", "initialer Text Box1", 100, TextField.ANY);

Der erste Parameter gibt die Überschrift der Box an, der zweite setzt den initialen Text, der dritte definiert die Länge der Box und der letzte definiert die erlaubten Werte der Box (hier alle). Für mehr Details siehe folgendes Kapitel.

Mit dem Statement

box1.addCommand(CMD_OK);

wird ein Kommando an die Textbox gebunden. Das ist für jedes Displayable mit der Methode addCommand möglich. Im Beispielprogramm werden zwei Kommandos an die Textbox gebunden, das Kommando OK und das Kommando EXIT.

Mit dem Statement

box1.setCommandListener(this);

wird erklärt, dass der CommandListener für box1 das MIDlet selbst ist (this). Wird ein Kommando auf dieser Textbox ausgelöst, so wird die Bearbeitung des Kommandos durch das Midlet erfolgen.

Die Erzeugung der zweiten Textbox erfolgt analog in getBox2().

Wenn das MIDlet gestartet wird, wird nach dem Konstruktor die Methode startApp() aufgerufen. Im Beispielprogramm wird dort als aktueller Screen die Textbox 1 gesetzt. Das erfolgt durch folgenden Code:

  Display.getDisplay(this).setCurrent(getBox1());

Es wird die Methode getBox1() gerufen, die die Textbox erzeugt. Mittels Display.getDisplay(this) wird das Display des MIDlets ermittelt und durch setCurrent() wird die gerade erzeugte Textbox zum aktuellen Screen. Diesen zeigt der Display also nach dem Start der Anwendung an.

Dabei ist der initale Text der Box zu sehen und die beiden Kommandos, OK und EXIT sind sichtbar. Diese Kommandos werden meist durch Softbuttons auf dem Handy dargestellt. Wird eines der Kommandos aktiviert, so wird der CommandListener der Textbox aufgerufen. In diesem Beispiel ist das das MIDlet selbst. Es wird die Methode commandAction aufgerufen.

Der Methode werden zwei Parameter übergeben: das aufgerufenen Kommando und das Displayable auf dem das Kommando aufgerufen wurde. Im Beispielprogramm wird zunächst getestet, ob das Kommando auf box1 aktiviert wurde. War das der Fall wird getestet, ob das Kommando OK gewählt wurde. War das der Fall, wird die box2 aktiviert. Das erfolgt genauso, wie die box1 in startApp() erzeugt wurde.

Wurde ein Kommando auf box2 aufgerufen, wird getestet, ob das Kommando BACK gewählt wurde. Ist das der Fall, wird die box1 wieder aktiviert. Mittels OK auf box1 und BACK auf box2 kann hin und her geschaltet werden.

Im letzten Teil der Methode wird getestet, ob das EXIT-Kommando gerufen wurde. Dieser Test erfolgt unabhängig von der jeweiligen Textbox. Das ist nicht zwingend so. Man hätte den Test auch in die obigen if-blöcke schreiben können. Es sollte hier nur demonstriert werden, dass man auf Kommandos auch unabhängig davon reagieren kann, wo das Kommando aufgerufen wurde.

Wurde EXIT gewählt, so wird die Anwendung beendet.

Persönliche Werkzeuge