J2ME v příkladech – vybíráme si

24. dubna 2003

Často potřebujeme nabídnout uživateli, aby si vybral jednu z několika možností a tím určil další chod aplikace. Nebo mu nabídneme možnost výběru několika položek najednou a kombinaci necháme na něm. Známe to z mnoha aplikací a ani aplikace pro mobilní telefony nejsou v tomto směru výjimkou. A právě v tomto článku se naučíme pracovat s komponentami pro výběr položek ze seznamu, ukážeme si, jak se tvoří a jak je kombinovat.

Třídy List a ChoiceGroup

Třídy List a ChoiceGroup mají na první pohled mnoho společného, ale přesto jsou odlišné. Třída List je potomkem třídy Screen, zatímco ChoiceGroup je potomek třídy Item. V praxi to znamená, že List můžeme umístit na displej samostatně, naproti tomu skupinu prvků ChoiceGroup musíme umístit na formulář. Může to vypadat jako zbytečnost, ale má to svoje opodstatnění, v následujících příkladech si ukážeme důvod.

Třída List implementuje rozhraní Choice, které nabízí tři typy seznamu: EXCLUSIVE, MULTIPLE a IMPLICIT. Zde je přehled jejich vlastností:

  • Choice.EXCLUSIVE – z nabídky je možno vybrat jen jeden prvek.
  • Choice.MULTIPLE – můžeme vybrat žádný, jeden nebo více prvků z nabídky.
  • Choice.IMPLICIT – položka z nabídky je vybrána v okamžiku, kdy je označena kurzorem.

Nejprve si vytvoříme jednoduchý seznam typu EXCLUSIVE. Tento typ seznamu umožňuje uživateli výběr jen jedné ze zobrazených možností. Ukázková aplikace bude simulovat objednávkový systém na osobní automobily. Nejprve mu dáme na výběr z několika barevných provedení. Zde je zdrojový kód prvního příkladu:

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class Abc extends MIDlet implements CommandListener {
  List lst_barva;
  Display disp;
  Command cmd_exit;
  Command cmd_next;
  Form frm_barva;
  StringItem si_barva;
  public Abc() {
    cmd_next = new Command(„Dalsi“, Command.SCREEN, 1);
    cmd_exit = new Command(„Konec“, Command.SCREEN, 1);
    /** Zde si vytvoříme instanci třídy LIST která bude obsahovat předem definovaný
    * seznam položek, atribut EXCLUSIVE říká že je možno vybrat jen jednu z položek.
    */
    lst_barva = new List(„Barva“, Choice.EXCLUSIVE);
    lst_barva.append(„Cervena“, null);
    lst_barva.append(„Modra“, null);
    lst_barva.append(„Zelena“, null);
    lst_barva.append(„Bila“, null);
    lst_barva.append(„Cerna“, null);
    lst_barva.addCommand(cmd_next);
    lst_barva.addCommand(cmd_exit);
    si_barva = new StringItem(„Vybrali jsme“, „“);
    frm_barva = new Form(„Barva“);
    frm_barva.addCommand(cmd_exit);
    frm_barva.append(si_barva);
  }
  public void startApp() {
    disp = Display.getDisplay(this);
    lst_barva.setCommandListener(this);
    disp.setCurrent(lst_barva);
  }
  public void pauseApp() { }
  public void destroyApp(boolean unconditional) {
    notifyDestroyed();
  }
  public void commandAction(Command c, Displayable d) {
    if(c == cmd_exit) { notifyDestroyed(); }
    if(c == cmd_next) { proceed(); }
  }
  public void proceed() {
    /** metodou getSelectedIndex zjistíme vybranou položku, ty jsou v seznamu indexovány
    * od nuly takže první položka je 0, druhá je 1 atd. */
    int select = lst_barva.getSelectedIndex();
    si_barva.setText(lst_barva.getString(select));
    frm_barva.setCommandListener(this);
    disp.setCurrent(frm_barva);
  }
}

Tento malý midlet zobrazí nabídku barev a umožní uživateli výběr jen jedné z nich. Po výběru barvy toto uživatel potvrdí příkazem Další. Jak je vidět na následujících obrázcích, je zobrazení třídy List plně závislé na implementaci Javy v mobilním telefonu. Jak už tedy správně tušíte, je to vysokoúrovňová komponenta.

Nokia 7210, třída LIST
List na mobilním telefonu Nokia 7210…

Motorola 720i, třída LIST
…na mobilním telefonu Motorola T720i…

Siemens C55 a třída LIST
…na Siemensu C55…

Sony Ericsson P800 - třída LIST
…a nakonec na SE P800.

Toto byl jednoduchý příklad jak nabídnou uživateli výběr jedné položky ze seznamu. Určitě se teď ptáte, jak to udělat, když chceme dát uživateli na výběr víc než jen jednu možnost z celé nabídky? Ani to není problém. Stačí pár úprav a aplikace toto umožní k naší plné spokojenosti. Použijeme seznam typu MULTIPLE, ve kterém je možné vybrat libovolný počet položek.

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class Abc extends MIDlet implements CommandListener {
  List lst_vybava;
  Display disp;
  Command cmd_exit;
  Command cmd_next;
  Form frm_vybava;
  StringItem si_vybava;
  public Abc() {
    cmd_next = new Command(„Dalsi“, Command.SCREEN, 1);
    cmd_exit = new Command(„Konec“, Command.SCREEN, 1);
    /** Zde si opět vytvoříme instanci třídy LIST která bude obsahovat předem definovaný
    * seznam položek, atribut MULTIPLE říká že je možno vybrat libovolný počet položek.
    */
    lst_vybava = new List(„Vybava“, Choice.MULTIPLE);
    lst_vybava.append(„Klimatizace“, null);
    lst_vybava.append(„Airbag“, null);
    lst_vybava.append(„Autoradio“, null);
    lst_vybava.append(„El. okna“, null);
    lst_vybava.addCommand(cmd_next);
    lst_vybava.addCommand(cmd_exit);
    si_vybava = new StringItem(„Zvolena vybava“, „“);
    frm_vybava = new Form(„Vybava“);
    frm_vybava.addCommand(cmd_exit);
    frm_vybava.append(si_vybava);
  }
  public void startApp() {
    disp = Display.getDisplay(this);
    lst_vybava.setCommandListener(this);
    disp.setCurrent(lst_vybava);
  }
  public void pauseApp() { }
  public void destroyApp(boolean unconditional) {
    notifyDestroyed();
  }
  public void commandAction(Command c, Displayable d) {
    if(c == cmd_exit) { notifyDestroyed(); }
    if(c == cmd_next) { proceed(); }
  }
  public void proceed() {
    /** nejprve si projdeme všechny prvky seznamu, jeho velikost zjistíme
    * metodou size(); */
    int prvky = lst_vybava.size();
    String str_vybava = „\n“;
    /** můžeme samozřejmě použít i cyklus typu for(int a=0; a<lst_vybava.size(); a++)
    * ale je dobré si uvědomit že pak se zjišťuje velikost seznamu při každém průběhu
    * cyklu což zpomaluje aplikaci */
    for(int a=0; a<prvky; a++) {
      if(lst_vybava.isSelected(a)) {
        // pokud je prvek vybraný přidá se jeho popis k seznamu
        str_vybava = str_vybava + lst_vybava.getString(a) + „\n“;
     }
   }
    si_vybava.setText(str_vybava);
    frm_vybava.addCommand(cmd_exit);
    frm_vybava.setCommandListener(this);
    disp.setCurrent(frm_vybava);
  }
}

Tento jednoduchý midlet nabídne uživateli několik možností vybavení automobilu a umožní mu vybrat libovolný počet položek. Po volbě Další zobrazí seznam vybraných položek jako text, jednotlivé položky jsou na oddělených řádcích. Jak to vypadá na mobilních telefonech, můžete vidět na následujících obrázcích:

Nokia 6310i nabídka položek
Menu na telefonu Nokia 6310i…

Nokia 6310i, seznam vybraných
…a seznam vybraných položek.

Siemens SL45i výběr
Zde je seznam na telefonu Siemens SL45i…

Siemens SL45i seznam vybraných položek
…a zde je výpis vybraných položek.

Co ale v případě, kdy chcete, aby některé položky byly vybrány už v okamžiku zobrazení nabídky a uživatel je mohl jen odebrat? Opět existuje jednoduché řešení, stačí použít metodu setSelectedIndex(int index, boolean selected). Vložte následující kód do předchozího příkladu na místo konstruktoru seznamu a aplikaci spusťte. Položka „Klimatizace“ a „Autoradio“ budou vybrány už v okamžiku zobrazení seznamu. Označené položky mají indexy 0 a 2, což napovídá, že položky seznamu jsou indexovány od nuly.

lst_vybava = new List(„Vybava“, Choice.MULTIPLE);
lst_vybava.append(„Klimatizace“, null);
lst_vybava.append(„Airbag“, null);
lst_vybava.append(„Autoradio“, null);
lst_vybava.append(„El. okna“, null);
lst_vybava.setSelectedIndex(0, true);
lst_vybava.setSelectedIndex(2, true);
lst_vybava.addCommand(cmd_next);
lst_vybava.addCommand(cmd_exit);

To byl popis seznamů typu EXCLUSIVE a MULTIPLE. Zbývá nám tedy seznam typu IMPLICIT. Tento typ seznamu má některé odlišnosti, které jej staví trochu mimo předchozí typy.

První odlišnost spočívá ve výběru položky. Zatímco dosud byla položka vybrána až tehdy, když ji uživatel „zaškrtnul“, v seznamu typu IMPLICIT je vybrána v okamžiku, kdy je na ní umístěn kurzor. Odpadají tedy zaškrtávátka, checkboxy a podobné grafické prvky, zobrazující aktuální výběr. Ten je prezentován kurzorem, kterým se po seznamu pohybujeme.

Další rozdíl je v použití rozhraní CommandListener. Pokud používáme seznam IMPLICIT, můžeme použít příkaz SELECT_COMMAND, který je zavolán v okamžiku, kdy chceme „označit“ položku. Ukážeme si v následujícím příkladu, jak to funguje. Nejprve vytvoříme seznam typu IMPLICIT a také odstraníme tlačítko pro pokračování, tato metoda bude spuštěna výběrem položky a použitím příkazu SELECT_COMMAND:

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class Abc extends MIDlet implements CommandListener {
  List lst_barva;
  Display disp;
  Command cmd_exit;
  Form frm_barva;
  StringItem si_barva;
  public Abc() {
    cmd_exit = new Command(„Konec“, Command.SCREEN, 1);
    /** Zde si vytvoříme instanci třídy LIST která bude obsahovat předem definovaný
    * seznam položek, atribut IMPLICIT určuje typ seznamu.
    */
    lst_barva = new List(„Barva“, Choice.IMPLICIT);
    lst_barva.append(„Cervena“, null);
    lst_barva.append(„Modra“, null);
    lst_barva.append(„Zelena“, null);
    lst_barva.append(„Bila“, null);
    lst_barva.append(„Cerna“, null);
    lst_barva.addCommand(cmd_exit);
    si_barva = new StringItem(„Vybrali jsme“, „“);
    frm_barva = new Form(„Barva“);
    frm_barva.addCommand(cmd_exit);
    frm_barva.append(si_barva);
  }
  public void startApp() {
    disp = Display.getDisplay(this);
    lst_barva.setCommandListener(this);
    disp.setCurrent(lst_barva);
  }
  public void pauseApp() { }
  public void destroyApp(boolean unconditional) {
    notifyDestroyed();
  }
  public void commandAction(Command c, Displayable d) {
    if(c == cmd_exit) { notifyDestroyed(); }
    // pouzijeme prikaz SELECT_COMMAND ktery je k dispozici v seznamu typu IMPLICIT
    if(c == List.SELECT_COMMAND) { proceed(); }
  }
  public void proceed() {
    /** metodou getSelectedIndex zjistíme vybranou položku, ty jsou v seznamu indexovány &nbsp
    * od nuly takže první položka je 0, druhá je 1 atd. */
    int select = lst_barva.getSelectedIndex();
    si_barva.setText(lst_barva.getString(select));
    frm_barva.setCommandListener(this);
    disp.setCurrent(frm_barva);
  }
}

Při běhu midletu nejlépe sami poznáte rozdíl v použití seznamu typu IMPLICIT. Jeho využití je velmi jednoduché, příjemné a praktické. S jeho pomocí se dají velmi elegantně tvořit nabídky funkcí aplikace nebo seznamy položek, které se po výběru zobrazí detailněji. V příštím článku si vysvětlíme, jak pracuje velmi podobná komponenta pro výběr prvků ChoiceGroup.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Předchozí článek tfdesign.cz
Štítky: Články

Mohlo by vás také zajímat

Nejnovější

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *