Image
27.6.2016 0 Comments

Programujeme v Jave /9.časť

Späť na úvod >> Späť na programovanie >> Späť na seriál

Menu a pop-up menu

V tejto časti seriálu o programovaní v Jave nadviažeme na tú predošlú, budeme sa teda venovať komponentom na tvorbu menu. Minule sme si ukázali, ako vytvoriť klasické menu (menu bar), ako vytvárať rôzne zložité hierarchie a ako priradiť jednotlivým položkám menu konkrétnu akciu, prípadne horúci kláves. Tentoraz si povieme o ďalších typoch položiek, ktoré môže menu obsahovať, ako aj o tom, ako vytvoriť a používať pop-up menu.

JCheckBoxMenuItem

Trieda JCheckBoxMenuItem je odvodená od JMenuItem a reprezentuje komponent zaškrtávacie políčko v menu. Tento komponent určite poznáte, slúži na nastavenie nejakého konkrétneho príznaku aplikácie prostredníctvom menu. Vytvorenie inštancie tohto komponentu prebieha rovnako ako vytvorenie inštancie JMenuItem, a teda najčastejším spôsobom, ktorý budete využívať, bude použitie konštruktora preberajúceho ako parameter textový popis položky, prípade ikonu. Použitie položiek JCheckBoxMenuItem demonštrujeme na nasledujúcom príklade:

 
import javax.swing.*;
import java.awt.event.*;
 
public class CheckBoxMenuItemTest extends JApplet {
 
  public void init() {
    JMenuBar menuBar = new JMenuBar();
    JMenu menu = new JMenu("Ovocie");
    JCheckBoxMenuItem jablko = new JCheckBoxMenuItem("Jablko");
    JCheckBoxMenuItem jahoda = new JCheckBoxMenuItem("Jahoda");
    JCheckBoxMenuItem slivka = new JCheckBoxMenuItem("Slivka");
    JCheckBoxMenuItem malina = new JCheckBoxMenuItem("Malina");
 
    menu.add(jablko);
    menu.add(jahoda);
    menu.add(slivka);
    menu.add(malina);
 
    menuBar.add(menu);
    this.setJMenuBar(menuBar);
  }
 
}

Po spustení sú všetky zaškrtávacie políčka v menu odznačené, teda ich stav je „nezaškrtnuté“. Ich stav je však možné ovplyvniť aj programovo (teda hneď po spustení programu alebo počas jeho behu) volaním metódy setState(), ktorá ako parameter preberá hodnotu typu boolean. Hodnota true signalizuje zaškrtnutú položku a false nezaškrtnutú položku. Keby sme teda chceli zaškrtnúť hneď na začiatku položku malina, vložili by sme do metódy init() volanie:

malina.setState(true);

Nastavenie počiatočného stavu zaškrtávacej položky je však možné aj použitím príslušného konštruktora (pozri dokumentáciu API).

Ako vidíte, komponent JCheckBoxMenuItem je použitý úplne rovnako ako komponent JMenuItem. Jeho inštancia je vytvorená rovnako a rovnakým spôsobom je pridaný do kontajnera. Odlišnosť však spočíva vo funkčnosti, pretože vybratie položky menu typu JCheckBoxMenuItem má vo väčšine prípadov za následok iba zmenu stavu tejto položky (zaškrtnutá/nezaškrtnutá). Aj keď je možné obslúžiť udalosti, ktoré prichádzajú do úvahy v súvislosti s použitím JMenuItem, nebudete asi tento fakt príliš využívať. Komponenty JCheckBoxMenuItem slúžia zväčša na nastavenie nejakých príznakov, ktorých stav je zisťovaný pri určitej akcii, ktorej priebeh môže byť týmito príznakmi modifikovaný. Znamená to teda, že môžete registrovať napr. poslucháčov ActionListener a reagovať na udalosť kliknutia na položku (resp. vybratia položky), ale väčšinou budete iba kontrolovať stav tohto zaškrtávacieho komponentu až vtedy, keď užívateľ vyzve program na nejakú konkrétnu akciu. V takom prípade budeme potrebovať metódu getState(), ktorá nám vráti hodnotu typu boolean signalizujúcu, či je tlačidlo zaškrtnuté (hodnota true), alebo nie (false).

JRadioButtonMenuItem

Posledným typom položky menu, ktorým sa budeme zaoberať, je JRadioButtonMenuItem. Tento komponent predstavuje prepínač v menu. Svojím spôsobom je podobný zaškrtávaciemu políčku s tým rozdielom, že prepínače sú združované do skupín a v každej skupine prepínačov môže byť vybraná (zaškrtnutá) vždy iba jediná položka. Vytvorenie prepínača menu prebieha opäť úplne rovnako ako vytvorenie klasickej menu položky JMenuItem alebo zaškrtávacieho políčka menu, teda použitím konštruktora preberajúceho ako parameter textový popis položky, prípadne ešte ikonu zobrazenú v položke. V prípade použitia prepínacej položky sa však musíte ešte postarať o jej správne priradenie do konkrétnej skupiny prepínačov, reprezentovanej triedou ButtonGroup, s ktorej použitím ste sa mali možnosť oboznámiť v piatej časti tohto seriálu v podkapitole venovanej komponentu JRadioButton. Ak to v rýchlosti zhrniem, inštanciu tejto triedy použijete na združovanie prepínačov. Ich pridanie do skupiny zabezpečuje metóda add() tejto triedy. Po pridaní prepínača do inštancie kontajnera ButtonGroup máte zaručené, že vždy iba jeden z prepínačov v tejto skupine bude označený a pri označení niektorého iného prepínača, bude pôvodne označený prepínač odznačený. Trieda ButtonGroup obsahuje niekoľko užitočných metód na zisťovanie informácií o položkách v skupine – počet, stav, výber a podobne. O týchto metódach som sa už zmieňoval v piatej časti tohto seriálu.

Použitie komponentu JRadioButtonMenuItem si takisto ukážeme na jednoduchom príklade (pre úsporu len metóda init()):

 
  public void init() {
    JMenuBar menuBar = new JMenuBar();
    JMenu menu = new JMenu("Ovocie");
    JRadioButtonMenuItem jablko = new JRadioButtonMenuItem("Jablko");
    JRadioButtonMenuItem jahoda = new JRadioButtonMenuItem("Jahoda");
    JRadioButtonMenuItem slivka = new JRadioButtonMenuItem("Slivka");
    JRadioButtonMenuItem malina = new JRadioButtonMenuItem("Malina");
    ButtonGroup bg = new ButtonGroup();
 
    bg.add(jablko);
    bg.add(jahoda);
    bg.add(slivka);
    bg.add(malina);
 
    menu.add(jablko);
    menu.add(jahoda);
    menu.add(slivka);
    menu.add(malina);
 
    menuBar.add(menu);
    this.setJMenuBar(menuBar);
  }

 

Ako vidíte, tento príklad je dosť podobný tomu predošlému. Rozdiel spočíva v tom, že kým v predchádzajúcom príklade ste mohli zaškrtnúť viacero položiek, v tomto je možné vybrať vždy iba jednu z nich, pričom tento výber je zrušený pri každom ďalšom novom výbere (označení položky). Pre triedu JRadioButtonMenuItem platí to isté ako pre JCheckBoxMenuItem, teda to, že ide o triedu odvodenú od triedy JMenuItem a je možné tiež registrovať všetky typy poslucháčov, ktorých registráciu JMenuItem povoľuje. Opäť však platí, že možno nebudete chcieť na zmenu výberu reagovať priamo, ale až pri výzve vykonať nejakú inú konkrétnu akciu.

Toto správanie sa dá implementovať vďaka použitiu triedy ButtonGroup, takže tento kód je o toto pridanie dlhší. Zisťovať momentálny stav prepínačov je možné práve prostredníctvom tejto triedy. O tom, akú techniku je pri tom možné použiť, som sa už zmieňoval v spomínanej piatej časti tohto seriálu.

Oddeľovače položiek menu

Občas je pre vzhľad menu žiaduce, aby boli niektoré položky od seba oddelené tzv. oddeľovačmi (angl. separator). Oddeľovače majú tvar vodorovnej čiary v menu, ktorou sú niektoré položky oddelené, čím je docielená väčšia prehľadnosť menu. V javovských aplikáciách je pridanie oddeľovačov do menu veľmi jednoduché – stačí použiť metódu addSeparator() implementovanú v triede JMenu. Volaním tejto metódy vložíte oddeľovač do menu za naposledy vloženú položku. Pre príklad uvádzam nasledujúci fragment kódu (ide o obmenu prvého príkladu):

 
  public void init() {
    JMenuBar menuBar = new JMenuBar();
    JMenu menu = new JMenu("Ovocie");
    JMenuItem jablko = new JMenuItem("Jablko");
    JMenuItem jahoda = new JMenuItem("Jahoda");
    JMenuItem slivka = new JMenuItem("Slivka");
    JMenuItem malina = new JMenuItem("Malina");
 
    menu.add(jablko);
    menu.add(slivka);
    menu.addSeparator();
    menu.add(jahoda);
    menu.add(malina);
 
    menuBar.add(menu);
    this.setJMenuBar(menuBar);
  }

V tomto jednoduchom kóde sme oddelili dve položky menu od ostatných dvoch.

Vkladanie oddeľovačov je, samozrejme, možné aj medzi iné menu položky (JCheckBoxMenuItem a JRadioButtonMenuItem) alebo do podmenu.

Pop-up menu

Pop-up menu sú ďalšou dôležitou súčasťou aplikácií GUI. Obyčajne je toto menu vyvolané kliknutím pravým tlačidlom niekde v používateľskej ploche aplikácie. Preto sa niekedy nazývajú aj lokálne menu, keďže ich obsah (zoznam položiek menu) závisí od miesta, kde bolo toto menu vyvolané. Použitie pop-up menu vo vašich aplikáciách je rovnako jednoduché ako použitie klasických menu. Do pop-up menu je možné vkladať položky JMenuItem, JRadioButtonMenuItem a JCheckBoxMenuItem rovnako ako do kontajnera JMenu. Ďalšia analógia spočíva v tom, že môžete pridávať ďalšie položky JMenu, takže je možné vytvárať hierarchické pop-up menu. Z tohto dôvodu pre obmedzenie zobrazených položiek je dobré, ak ešte pred zobrazením pop-up menu skontrolujete miesto, na ktorom vznikla požiadavka na jeho zobrazenie, a upravíte patrične podľa toho zoznam položiek menu.

V knižnici Swing je pop-up menu reprezentované triedou JPopupMenu, ktorá poskytuje metódy na pridávanie položiek do pop-up menu aj na jeho zobrazovanie. Vytvorenie inštancie je možné jednoducho pomocou bezparametrického konštruktora triedy JPopupMenu, rovnako ako pridávanie nových položiek je možné prostredníctvom metódy add() (či už ide pridávanie položiek menu, alebo podmenu). Zabezpečiť však správne vyvolanie a zobrazenie pop-up menu si vyžaduje trošku viac práce, než to bolo v prípade klasických menu. Poďme sa najprv pozrieť na príklad:

 
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
 
public class PopupMenuTest extends JApplet {
  private JPopupMenu jpm;
 
  public void init() {
    jpm = new JPopupMenu();
    JMenuItem akcia1 = new JMenuItem("Akcia 1");
    JMenuItem akcia2 = new JMenuItem("Akcia 2");
    JMenuItem akcia3 = new JMenuItem("Akcia 3");
    JMenuItem akcia4 = new JMenuItem("Akcia 4");
    JMenu ostatne = new JMenu("Ostatné");
 
    ostatne.add(akcia3);
    ostatne.add(akcia4);
 
    jpm.add(akcia1);
    jpm.add(akcia2);
    jpm.add(ostatne);
 
    getContentPane().addMouseListener(new MyAdapter());
  }
 
  class MyAdapter extends MouseAdapter {
    public void mouseClicked(MouseEvent e) {
      jpm.show((Component) e.getSource(), e.getX(), e.getY());
    }
  }
 
}

Pokiaľ tento kód skompilujete a spustíte (napr. v appletvieweri) a kliknete niekde v používateľskej časti okna (časť vnútri okna), zobrazí sa vám pop-up menu podobne.

Význam vnútornej triedy MyAdapter vám ešte nemusí byť príliš jasný, rovnako ako posledný riadok v metóde init(), pretože ide o registráciu poslucháča typu MouseListener a my používame triedu MouseAdapter, čo nezodpovedá konvenciám udalostného modelu, o ktorých som písal vo štvrtej časti tohto seriálu v odseku venovanom práve udalostnému modelu. Vysvetlenia sa dočkáte v budúcom pokračovaní seriálu, v ktorom si povieme o tom, ako obsluhovať jednotlivé udalosti, ktoré vzniknú v súvislosti s používateľským vstupom z klávesnice a myši. Zatiaľ sa uspokojme s tým, že táto trieda a posledný riadok metódy init() nám zabezpečí zobrazenie pop-up menu vnútri komponentu, v ktorom túto triedu ako poslucháča zaregistrujeme. Keďže sme zaregistrovali tohto poslucháča v kontajneri appletu, bude pop-up menu zobrazované vždy po kliknutí hocikde v kontajneri, teda na ploche appletu. Naša implementácia má však ešte jednu malú chybičku krásy – pop-up menu je zobrazené vždy pri kliknutí hociktorým tlačidlom myši, teda nielen pravým, ale aj ľavým (prípadne aj stredným). Tento nežiaduci fakt sa v nasledujúcej časti tiež naučíme odstrániť, takisto sa naučíme rozoznávať jednotlivé stavy tlačidiel myši.

Čo sa týka zobrazenia pop-up menu, to je zabezpečené volaním metódy show() triedy JPopupMenu. Tejto metóde je potrebné prostredníctvom parametrov odovzdať odkaz na komponent, vnútri (alebo ak chcete na ploche) ktorého má byť pop-up menu zobrazené, a takisto x-ovú a y-ovú súradnicu pozície ľavého horného rohu pop-up menu (teda miesta, kde má byť pop-up menu zobrazené). Komponentom, na ktorého ploche má byť pop-up menu zobrazené, môže byť akákoľvek inštancia triedy Component alebo jej potomkovských tried, z čoho vyplýva, že ním môže byť akýkoľvek komponent AWT alebo Swing. Súradnice zobrazovaného pop-up menu sú relatívne vzhľadom na ľavý horný roh komponentu, v ktorom sa pop-up menu zobrazí.

Vzhľadom na všetky skutočnosti, ktoré už poznáte, by nemal byť pre vás problém implementovať pop-up menu tak, aby sa jeho obsah menil v závislosti od toho, v ktorom mieste vznikla požiadavka na jeho zobrazenie, resp. kliknutím na ktorý komponent požiadal používateľ o zobrazenie pop-up menu. Jednou možnosťou je implementovať logiku určujúcu, ktoré položky menu budú zobrazené a akým spôsobom, priamo do metódy obsluhujúcej udalosť kliknutia myšou. Druhá možnosť je vytvoriť si viacero inštancií pop-up menu (pre každý komponent, ktorý má mať svoje pop-up menu, vlastnú) a v obslužnej metóde udalosti iba rozoznať, o ktorý komponent ide, a na základe toho použiť príslušnú inštanciu. Druhý spôsob demonštruje nasledujúci príklad:

 
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
 
public class PopupMenuTest extends JApplet {
  private JPopupMenu jpm1, jpm2;
  private JLabel label1, label2;
 
  public void init() {
    getContentPane().setLayout(new GridLayout(1, 2));
 
    jpm1 = new JPopupMenu();
    jpm2 = new JPopupMenu();
    JMenuItem akcia1 = new JMenuItem("Akcia 1");
    JMenuItem akcia2 = new JMenuItem("Akcia 2");
    JMenuItem akcia3 = new JMenuItem("Akcia 3");
    JMenuItem akcia4 = new JMenuItem("Akcia 4");
 
    jpm1.add(akcia1);
    jpm1.add(akcia2);
    jpm2.add(akcia3);
    jpm2.add(akcia4);
 
    label1 = new JLabel("Popis 1");
    label2 = new JLabel("Popis 2");
    MyAdapter ma = new MyAdapter();
    label1.addMouseListener(ma);
    label2.addMouseListener(ma);
 
    getContentPane().add(label1);
    getContentPane().add(label2);
  }
 
  class MyAdapter extends MouseAdapter {
 
    public void mouseClicked(MouseEvent e) {
      JPopupMenu jpm = null;
      Object source = e.getSource();
      if (source == label1) jpm = jpm1;
      else jpm = jpm2;
 
      jpm.show((Component) source, e.getX(), e.getY());
    }
 
  }
 
}

Ako vidíte, vytvorili sme dve inštancie pop-up menu a do kontajnera appletu vložili dva textové popisy. Prvé pop-up menu je zobrazené po kliknutí na prvý textový popis, druhé po kliknutí na druhý textový popis. V metóde obsluhujúcej udalosť kliknutia myšou vyberieme príslušnú inštanciu pop-up menu na základe porovnania zdrojového objektu udalosti a jedného textového popisu. Vďaka tomu môžeme použiť pre oba textové popisy jednu a tú istú inštanciu triedy na obsluhu udalostí kliknutia myši (MyAdapter).

Záver

Po tejto časti by vám z oblasti tvorby menu a jeho použitia malo byť jasné takmer všetko, či už ide o pop-up menu, alebo klasické menu (menu bar). V budúcej časti seriálu sa budeme venovať udalostnému modelu a udalostiam súvisiacim s menu, myšou a klávesnicou. Dovtedy dovidenia.

 

 

Autor: Andrej Chu

Nechajte si posielať prehľad najdôležitejších správ emailom

Mohlo by Vás zaujímať

ITPro

Linux súkromne i pracovne v2.0 (14. časť): Small Business Server

09.11.2016 14:57

Pojem Small Business Server (malý firemný server) začala používať spoločnosť Microsoft ešte v roku 2000 na označenie servera, ktorý ­dokázal plniť úlohy niekoľkých samostatných serverov. Aplikačná vrs ...

ITPro

Industry 4.0: Fikcia alebo už realita?

09.11.2016 14:52

Štvrtá priemyselná revolúcia je pomenovanie rozsiahlych zmien prudko vstupujúcich do súčasného priemyslu. Nositeľom týchto zmien je digitalizácia výroby a optimalizácia všetkých podnikových procesov v ...

ITPro

Vývoj aplikácií UWP pre Xbox One II.

09.11.2016 14:47

V predošlej časti sme ukázali postup, ako si ­vytvoriť vývojársky účet a aktivovať vývojársky režim na hernej konzole Xbox One, aby ste mohli testovať svoje aplikácie. Výhodou hernej konzoly Xbox je v ...

Žiadne komentáre

Vyhľadávanie

Kyocera - prve-zariadenia-formatu-a4-s-vykonom-a3

Najnovšie videá