Mobiltelefonapplikationer med Java ME: Lektion 5

Idag: Användargränssnittet i en MIDlet
  • Display och Displayable
  • Command
  • Alert
  • TextBox

Klicka på startknappen i den lilla mediespelaren ovan för att lyssna på lektionen. (Man kan behöva vänta en stund på att ljudfilen laddas ner.) Om mediespelaren inte syns, eller om det inte fungerar av något annat skäl, kan man klicka här för att ladda ner mp3-filen (ca 25 minuter, ca 11 megabyte). Beroende på hur webbläsaren är konfigurerad kan det kräva ett separat mp3-spelarprogram av något slag.

Tänk på att lektionerna ger en översikt och introduktion. Du måste läsa i kursboken och arbeta med övningarna för att tillgodogöra dig kursen.

"Bild" 1: Den enklast möjliga MIDlet:en

En MIDlet måste ärva från klassen MIDlet (fullständigt namn: javax.microedition.midlet.MIDlet).

Klassen MinstaMIDleten från filen MinstaMIDleten.java:
(Radnumren ingår inte i programmet.)

    1   // Den minsta MIDlet-klass som går att kompilera
    2
    3   import javax.microedition.midlet.*;
    4
    5   public class MinstaMIDleten extends MIDlet {
    6       public void destroyApp(boolean unconditional) { }
    7       public void pauseApp() { }
    8       public void startApp() { }
    9   }

Bild 2: Skapa ett projekt i WTK

Skapa ett projekt i WTK

Bild 3: Bygg och kör

Lägg dit filen filen MinstaMIDleten.java i projektets källkodskatalog, exempelvis C:\WTK23\apps\Minsta MIDleten\src.

Bygg. Kör.

Bygg och kör projektet i WTK

Bild 4: Emulatorn

Det finns två kommandoknappar på telefonen. Klicka på knappen under Launch.

Vad händer? Svar: Ingenting! Varför?

Minsta MIDleten i emulatorn

Bild(er) 5: En MIDlet som syns

Minsta synliga MIDleten i emulatorn     Alert-meddelandet i emulatorn

"Bild" 6: Koden till MIDleten som syns

Klassen MinstaSynligaMIDleten från filen MinstaSynligaMIDleten.java:
(Radnumren ingår inte i programmet.)

    1   // En MIDlet-klass som syns när den körs
    2   
    3   import javax.microedition.midlet.*;
    4   import javax.microedition.lcdui.*;
    5   
    6   public class MinstaSynligaMIDleten extends MIDlet {
    7       private Display displayen;
    8       private Alert varningen;
    9   
   10       public MinstaSynligaMIDleten() {
   11           varningen = new Alert("Hej!", "Hej, världen!", null, null);
   12       }
   13       public void destroyApp(boolean unconditional) { }
   14       public void pauseApp() { }
   15       public void startApp() {
   16           displayen = Display.getDisplay(this);
   17           displayen.setCurrent(varningen);
   18       }
   19   }

"Bild" 7: Repetition: Paket, klasser och metoder

  • Paketet javax.microedition.midlet
  • Paketet javax.microedition.lcdui
  • Klassen MIDlet
  • Klassen Display
  • Klassen Alert
  • Klassen Displayable (superklass till Alert och några till)
  • Den statiska metoden Display.getDisplay(MIDlet)
  • Metoden Display.setCurrent(Displayable)

Bild 8: API-dokumentationen

Finns länkade från kursens hemsida (samt länkar om var man kan ladda hem dem):

MIDP-API-specen i en Internet Explorer

Bild(er) 9: Klassen TextBox

Som alternativ till varningsmeddelandet med Alert provar vi nu textrutan TextBox:

Emulatorn: Nu ska vi starta textrutetestet     Emulatorn: Nu har vi startat textrutetestet     Emulatorn: Vi kan skriva i textrutan

"Bild" 10: Koden till TextBox-testet

Klassen TextBoxTest från filen TextBoxTest.java:

    1   // En MIDlet som visar en textruta
    2   
    3   import javax.microedition.midlet.*;
    4   import javax.microedition.lcdui.*;
    5   
    6   public class TextBoxTest extends MIDlet {
    7       private Display displayen;
    8       private TextBox textrutan;
    9   
   10       public TextBoxTest() {
   11           textrutan = new TextBox("Hej!", "Hej, världen!", 20, 0);
   12       }
   13       public void destroyApp(boolean unconditional) { }
   14       public void pauseApp() { }
   15       public void startApp() {
   16           displayen = Display.getDisplay(this);
   17           displayen.setCurrent(textrutan);
   18       }
   19   }

Bild 11: Jaha, och nu då?

Hur ska man komma ur textrutan? Det finns ju ingen Exit-knapp.

Emulatorn: Vi kan skriva i textrutan

Bild(er) 12: Kommandon!

Samma textruta, men nu står det Exit nere till vänster!

Emulatorn: Nu ska vi starta textrutetestet     Emulatorn: Nu har vi startat textrutetestet, och det finns ett Exit-kommando     Emulatorn: Nu har vi kört Exit-kommandot och avslutat MIDleten

"Bild" 13: Koden till kommando-testet

Klassen Kommandotest från filen Kommandotest.java:

    1   // En MIDlet som visar en textruta och ett Exit-kommando
    2   
    3   import javax.microedition.midlet.*;
    4   import javax.microedition.lcdui.*;
    5   
    6   public class Kommandotest extends MIDlet {
    7       private Display displayen;
    8       private TextBox textrutan;
    9       private Command exitkommandot;
   10   
   11       public Kommandotest() { }
   12       public void destroyApp(boolean unconditional) { }
   13       public void pauseApp() { }
   14       public void startApp() {
   15           textrutan = new TextBox("Hej!", "Hej, världen!", 20, 0);
   16   
   17           exitkommandot = new Command("Exit", Command.EXIT, 0);
   18           textrutan.addCommand(exitkommandot);
   19           Exitkommandolyssnare lyssnaren = new Exitkommandolyssnare();
   20           textrutan.setCommandListener(lyssnaren);
   21           
   22           displayen = Display.getDisplay(this);
   23           displayen.setCurrent(textrutan);
   24       }
   25   
   26       class Exitkommandolyssnare implements CommandListener {
   27           public void commandAction(Command c, Displayable s) {
   28               notifyDestroyed();
   29           }
   30       }
   31   }

"Bild" 14: Nästan samma kod, men utan en särskild CommandListener-klass

Klassen Kommandotest2 från filen Kommandotest2.java:

    1   // En MIDlet som visar en textruta och ett Exit-kommando
    2   
    3   import javax.microedition.midlet.*;
    4   import javax.microedition.lcdui.*;
    5   
    6   public class Kommandotest2 extends MIDlet implements CommandListener {
    7       private Display displayen;
    8       private TextBox textrutan;
    9       private Command exitkommandot;
   10   
   11       public Kommandotest2() { }
   12       public void destroyApp(boolean unconditional) { }
   13       public void pauseApp() { }
   14       public void startApp() {
   15           textrutan = new TextBox("Hej!", "Hej, världen!", 20, 0);
   16   
   17           exitkommandot = new Command("Exit", Command.EXIT, 0);
   18           textrutan.addCommand(exitkommandot);
   19           textrutan.setCommandListener(this);
   20           
   21           displayen = Display.getDisplay(this);
   22           displayen.setCurrent(textrutan);
   23       }
   24   
   25       public void commandAction(Command c, Displayable s) {
   26           notifyDestroyed();
   27       }
   28   }

"Bild" 15: Repetition: Paket, klasser och metoder

  • Klassen TextBox
  • Klassen Command
  • Gränssnittet CommandListener
  • Metoden Displayable.addCommand(Command)
  • Metoden Displayable.setCommandListener(CommandListener)
  • Metoden CommandListener.commandAction(Command, Displayable)

Bild(er) 16: Flera kommandon

Det finns två kommandoknappar på telefonen. Vad händer om man har mer än två kommandon?

Emulatorn: Nu ska vi starta MIDleten     Emulatorn: Nu har vi startat MIDleten

Bild(er) 17: En meny med flera kommandon

Ett kommando visas, och de andra grupperas ihop i en meny.

Emulatorn: Nu ska vi starta MIDleten     Emulatorn: Nu har vi startat MIDleten

Bild(er) 18: Vad de här kommandona ska göra

Kommandona Tripp, Trapp och Trull skriver ut en text i textrutan.

Kommandot Hjälp visar en helt ny textruta med instruktioner.

Emulatorn: Nu ska vi starta MIDleten     Emulatorn: Nu har vi startat MIDleten     Emulatorn: Nu har vi startat MIDleten

"Bild" 19: Koden till MIDleten med flera kommandon

Klassen FleraKommandon från filen FleraKommandon.java:

    1   // En MIDlet med en textruta som har flera kommandon
    2   
    3   import javax.microedition.midlet.*;
    4   import javax.microedition.lcdui.*;
    5   
    6   public class FleraKommandon extends MIDlet implements CommandListener {
    7       private Display displayen;
    8       private TextBox textrutan;
    9       private TextBox hjälprutan;
   10       private Command exitkommandot;
   11       private Command trippkommandot;
   12       private Command trappkommandot;
   13       private Command trullkommandot;
   14       private Command hjälpkommandot;
   15   
   16       public FleraKommandon() { }
   17       public void destroyApp(boolean unconditional) { }
   18       public void pauseApp() { }
   19       public void startApp() {
   20           textrutan = new TextBox("Hej!", "Hej, världen!", 20, 0);
   21           hjälprutan =
   22               new TextBox("Instruktioner",
   23                           "Tryck på knapparna och var glad.", 100, 0);
   24   
   25           exitkommandot = new Command("Exit", Command.EXIT, 0);
   26           trippkommandot = new Command("Tripp", Command.SCREEN, 0);
   27           trappkommandot = new Command("Trapp", Command.SCREEN, 0);
   28           trullkommandot = new Command("Trull", Command.SCREEN, 0);
   29           hjälpkommandot = new Command("Hjälp", Command.SCREEN, 0);
   30   
   31           textrutan.addCommand(exitkommandot);
   32           textrutan.addCommand(trippkommandot);
   33           textrutan.addCommand(trappkommandot);
   34           textrutan.addCommand(trullkommandot);
   35           textrutan.addCommand(hjälpkommandot);
   36           textrutan.setCommandListener(this);
   37   
   38           displayen = Display.getDisplay(this);
   39           displayen.setCurrent(textrutan);
   40       }
   41   
   42       public void commandAction(Command c, Displayable s) {
   43           if (c == exitkommandot)
   44               notifyDestroyed();
   45           else if (c == trippkommandot)
   46               textrutan.setString("Du tryckte på Tripp!");
   47           else if (c == trappkommandot)
   48               textrutan.setString("Du tryckte på Trapp!");
   49           else if (c == trullkommandot)
   50               textrutan.setString("Du tryckte på Trull!");
   51           else if (c == hjälpkommandot)
   52               displayen.setCurrent(hjälprutan);
   53       }
   54   }

Bild(er) 19: Hjälp-kommandot

Hjälp-kommandot byter till en annan textruta, med hjälp av koden displayen.setCurrent(hjälprutan):

Emulatorn: Nu har vi startat MIDleten     Emulatorn: Nu har vi startat MIDleten

Läsanvisningar

I den nya kursboken Kicking Butt with MIDP and MSA motsvaras den här lektionen av kapitel 3, Quick Start och kapitel 7, Basic User Interface.

I den gamla kursboken Beginning J2ME motsvaras den här lektionen av kapitel 5, Creating a User Interface. Kapitel 5 är ett av de viktigaste i hela boken, och det är egentligen bara stycke tre och fyra uppifrån på sidan 63, de som handlar om metoden setInitialInputMode, som man kan läsa lite mer kursivt.

Här är några frågor som kan användas som instuderingsfrågor:

  1. Vad menas med abstraktion och upptäckt (engelska: discovery) i MIDP-sammanhang?
  2. För det mesta bör man använda abstraktion. Varför?
  3. Det finns åtminstone två anledningar till att man ibland i stället vill använda upptäckt. Vilka?
  4. Vad är det för skillnad på klasserna Display och Displayable?
  5. Var hittar man metoden setCurrent, och vad gör den?
  6. Vilka är de viktigaste klasserna i paketet javax.microedition.lcdui?
  7. En MIDlet har, som alla Java-klasser, en konstruktor, men också en metod som heter startApp. Kan man inte lämna startApp tom, och lägga all initieringskod, med getDisplay med mera, i konstruktorn?
  8. Hur kan man få reda på information om mobiltelefonens display?
  9. Varför kan man behöva veta sådana detaljer om displayen på telefonen?
  10. Det vanliga sättet att ge "kommandon" i vanliga skrivbords-Java (dvs J2SE, Java 2 Standard Edition) är genom att klicka med musen på en knapp. Java-programmet placerar ut knappar av klassen JButton på skärmen, och när användaren klickar på en knapp anropas en metod som heter actionPerformed. Varför gör man inte likadant i MIDP?
  11. Hur gör man i stället?
  12. Kommandon har olika typer, som CANCEL och HELP. Varför? (Det förklaras inte särskilt bra i boken, så du kan behöva läsa om klassen Command i API-dokumentationen för MIDP.
  13. Kommandon har olika prioriteter. Varför?
  14. MIDP innehåller gränssnittet (engelska: interface) CommandListener. Vad har man det till?
  15. Vad är en tråd (engelska: "thread")? (Det förklaras inte i kapitlet, men står förmodligen i en grundläggande Java-bok.)
  16. Ibland vill man göra saker som tar lång tid, till exempel göra komplicerade beräkningar eller koppla upp sig via Internet, som svar på att användaren ger ett kommando. Boken rekommenderar att man då inte gör allt det jobbet i hanterarmetoden, utan startar en egen tråd för det. Varför?
  17. Vad är klassen Screen?
  18. Vad är klassen Ticker?
  19. MIDP-program ska helst inte kräva att användaren matar in långa texter. Varför?
  20. När man skapar en TextBox anger man en maxstorlek. Vad mäts den i? Rader, tecken, pixlar, eller något annat? (Glöm inte att den sortens information ofta hittas enklast i API-dokumentationen.)
  21. Man kan ange begränsningar (engelska: constraints) på vad man kan mata in i en TextBox. Hur gör man det?
  22. Hur skulle man skapa en TextBox för inmatning av en e-postadress?
  23. Hur skulle man skapa en TextBox för inmatning av en e-postadress, som dessutom är lite hemlig och inte bör lagras i telefonens eventuella listor för automatisk ifyllning av senare inmatning?
  24. Varför kan flaggan PASSWORD vara olämplig att använda vid inmatning på en mobiltelefon?
  25. Vad är det för skillnad på en tidsbegränsad (engelska: timed) och en modal (engelska: modal) varning (engelska: alert)?
  26. Hur anger man hur länge en varning ska visas?
Om du vill skriva svar på instuderingsfrågorna, räcker det för de flesta frågorna med en eller några få meningar.

Programmeringsövningar

  1. Skapa ett projekt, skriv in (ladda inte ner) och provkör den enklast möjliga MIDleten från lektionen ovan.
  2. Skapa ett projekt, skriv in (eller ladda ner) och provkör den enklaste synliga MIDleten från lektionen ovan, den som visar en Alert.
  3. Ändra i koden för den Alert-visande MIDleten så att den visar en TextBox i stället, ungefär som i exemplet med TextBoxTest.
  4. Skapa ett projekt, ladda ner (eller skriv in) och provkör MIDleten med flera kommandon från lektionen ovan.
  5. Lägg till ett kommando som tar bort hjälprutan och visar den ursprungliga textrutan igen. (Tips: Tänk på att det är varje textruta, och inte MIDleten, som har kommandon.) [Lösningsförslag]

Föregående lektion | Lektionslista | Inlämningsuppgift 1


Thomas Padron-McCarthy (Thomas.Padron-McCarthy@oru.se), 29 augusti 2008