OZNAM

V pondelok nebude cvicenie!

Ciele

  1. Oboznámiť sa s tvorbou grafického používateľského rozhrania.
  2. Oboznámiť sa s udalosťami riadeným vykonávaním programu.
  3. Implementovať grafické používateľské rozhranie Swing pre hru Minesweeper.

Úvod

    Dnes vytvoríme grafické používateľské rozhranie pre našu hru Minesweeper.

Postup

  1. Pridajte do triedy Minesweeper nasledujúcu metódu. Táto metóda sa bude používať pre začatie hrania novej hry.
    
    public void newGame() {
        Field field = new Field(setting.getRowCount(), setting.getColumnCount(), setting.getMineCount());
        startMillis = System.currentTimeMillis();
        userInterface.newGameStarted(field);
    }
    
    Teraz ju možete použiť v konštruktore Minesweeper na začatie prvej hry.
  2. V nasledujúcom kroku pridajte do projektu Minesweeper triedy pre grafické používateľské rozhranie.
    Úloha: Pridajte do projektu (do adresára src) obsah archívu swingui.zip.
    Archív obsahuje adresár img s obrázkami a balík minesweeper.swingui. V balíku minesweeper.swingui sú triedy TileComponent a SwingUI. Oboznámte sa s triedami TileComponent a SwingUI.
    • Trieda TileComponent je grafický komponent slúžiaci pre vykreslenie jednej dlaždice hracieho poľa.
    • Trieda SwingUI predstavuje okno hry a zároveň implementuje rozhranie UserInterface.
  3. Nasledujúcim krokom je zobrazenie hracej plochy v okne aplikácie.
    Úloha: Implementujte metódu public void newGameStarted(Field field) triedy SwingUI.
    V rámci tejto metódy je potrebné vykonať nasledujúce kroky:
    • Inicializovať premennú objektu field argumentom metódy newGameStarted(Field field).
    • Odstrániť všetky komponenty, ktoré obsahuje panel contentPanel prostredníctvom volania contentPanel.removeAll() (Komponenty sa odstraňujú z dôvodu vytvorenia nového hracieho poľa). Nastavte pre panel contentPanel manažér rozmiestnenia na typ GridLayout prostredníctvom aplikácie
      
      contentPanel.setLayout(new GridLayout(field.getRowCount(), field.getColumnCount()))
      
    • Vytvoriť pre každú dlaždicu hracieho poľa grafický komponent triedy TileComponent spätý s danou dlaždicou.
    • Tento komponent následne pridajte do kontajnera hracieho poľa contentPanel pomocou metódy Component add(Component comp).
    • Pre každý komponent dlaždice je potrebné nastaviť spracovanie udalosti pre stlačenie tlačidla myši - MouseListener. Pre nastavenie spracovania udalosti použite metódu void addMouseListener(MouseListener l). Trieda SwingUI implementuje rozhranie MouseListener.
      
      public class SwingUI extends JFrame implements UserInterface, MouseListener {...}
      
    • Aplikovať metódu update() triedy SwingUI pre zobrazenie počiatočného stavu hracieho poľa.
    • Aplikovať metódu pack() triedy SwingUI zabezpečujúcu rozloženie komponentov hlavného okna hry Minesweeper s cieľom minimalizácie veľkosti okna (kompaktný tvar).
    Úloha: Implementujte metódu public void update() triedy SwingUI. V tejto metóde je nutné nad každým grafickým komponentom triedy TileComponent aplikovať metódu updateStyle(). Taktiež je potrebné aktualizovať počítadlo zostávajúcich neoznačených mín aplikovaním metódy setMinesLeftLabelText() triedy SwingUI.
    Poznámka: Komponenty TileComponent sú uložené priamo v paneli contentPanel. Prechádzať prvkami môžete prostredníctvom metód contentPanel.getComponentCount() a contentPanel.getComponent(index).
  4. Ďalším krokom je definovanie spracovania udalosti nad dlaždicami hracej plochy hry Minesweeper.
    Úloha: Implementujte metódu public void mousePressed(MouseEvent e) triedy SwingUI. Táto metóda je implementáciou reakcie na stlačenie tlačidla myši nad grafickým komponentom triedy TileComponent.
    Vykonanie tejto metódy je určené nasledujúcimi krokmi:
    • Podmienkou reakcie na stlačenie myši je stav hry GameState.PLAYING. V inom prípade by nemalo byť hracie pole menené.
    • Pri stlačení ľavého tlačidla myši je potrebné aplikovať metódu void openTile(int row, int column) objektu hracieho poľa triedy Field. Pozícia grafického komponentu dlaždice v hracom poli je prístupná v objekte grafického komponentu TileComponent.
      Poznámka: Komponent dlaždice nad ktorou bola myš stlačená je možné získať z objektu udalosti nasledovne: TileComponent button = (TileComponent)e.getSource();
      Poznámka: Pre identifikovanie stlačenia ľavého tlačidla myši použite statickú metódu isLeftMouseButton(MouseEvent e) triedy SwingUtilities.
    • V prípade, že sa zmenil stav hry na stav GameState.FAILED, je potrebné vypísať používateľovi v dialógovom okne informáciu o chybnom ukončení hry.
      Poznámka: Pre zobrazenie dialógového okna s požadovanou informáciou použite statickú metódu void showMessageDialog(Component parentComponent, Object message, String title, int messageType) triedy JOptionPane.
    • V prípade, že sa zmenil stav hry na stav GameState.SOLVED, je potrebné vypísať používateľovi v dialógovom okne informáciu o úspešnom ukončení hry. Taktiež je potrebné zapísať používateľa do tabuľky najlepších časov použitím metódy void addPlayerTime(String name, int time) triedy BestTimes. Pre získanie času hrania hry použite metódu getPlayingSeconds() objektu triedy Minesweeper. Pre získanie mena používateľa použite výraz System.getProperty("user.name"), ktorý poskytne hodnotu systémovej premennej prostredia user.name predstavujúcu meno používateľa prihláseného do systému.
    • Pri stlačení pravého tlačidla myši je potrebné aplikovať metódu void markTile(int row, int column) objektu hracieho poľa triedy Field. Pre identifikovanie stlačenia pravého tlačidla myši použite statickú metódu isRightMouseButton(MouseEvent e) triedy SwingUtilities.
    • Po vykonaní odkrytia resp. označenia dlaždice je potrebné prekresliť hracie pole aplikovaním metódy update() triedy SwingUI.
  5. V tomto kroku je potrebné realizovať zobrazenie zoznamu najlepších časov hráčov hry Minesweeper.
    Úloha: Vytvorte dialóg na zobrazenie času najlepších hráčov.
    Inšpirujte sa nasledujúcim vzorom:
    Obr.: : Vzor dialógu pre zobrazenie času najlepších hráčov
    • Vytvorte triedu BestTimesDialog typu JDialog („File > New File... > Java GUI Forms > Swing GUI Forms”). Nezabudnite zaradiť túto triedu do balíkaminesweeper.swingui.
    • Odstráňte metódu main v triedeBestTimesDialog.
    • V konštruktore triedy BestTimesDialog implementujte zobrazenie najlepšieho skóre získaného aplikovaním metódy getBestTimes() nad objektom triedy Minesweeper. Informácie o časoch zobrazte do grafického prvku JTextArea (pomocou metódy void setText(String t)).
      Poznámka: Pre vycentrovanie dialógového okna nad oknom hracej plochy použite metódu setLocationRelativeTo(Component c) nad objektom dialógového okna.
    • Zaregistrujte nad tlačidlom s textom „OK” obsluhu udalosti ActionListener. V prostredí NetBeans v zobrazení návrhu dialógového okna označte komponent tlačidla. V okne s názvom „Properties” zvolíte záložku „Events” a kurzor nastavíte do textového poľa pre zadanie názvu udalosti „actionPerformed”. Stlačte „Enter”. V zdrojovom kóde sa automaticky vytvorí metóda pre spracovanie udalosti. Ak bude grafický komponent tlačidla pomenovaný názvom okButton, tak metóda bude vygenerovaná v nasledujúcej forme:
      
      private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {
          // TODO add your handling code here:
      }
      
      Implementujte spracovanie udalosti pre stlačenie tlačidla nasledovne:
      
      setVisible(false);
      dispose();
      
      Daný kód zatvorí dialógové okno a uvoľní zdroje späté s oknom.
    • V triede SwingUI dodajte implementáciu stlačenia menu „Game > Best Times...”. Na vyhľadanie položky menu bestTimesMenuItem použite okno „Inspector”. Postupujte podľa postupu uvedenom hore. Implementácia reakcie na udalosť je nasledovná.
      
      new BestTimesDialog(this, true).setVisible(true);
      
  6. Pre zaradenie implementovaného grafického používateľského rozhrania do hry Minesweeper je potrebné vykonať úpravu v hlavnej triede aplikácie podľa nasledujúcich úloh.
    Úloha: V triede Minesweeper definujte premennú private static final String DEFAULT_UI = "swing". Na základe hodnoty tejto premennej sa určí, aký typ používateľského rozhrania bude použitý (SwingUI, alebo ConsoleUI).
    Úloha: Implementujte metódu private UserInterface create(String name) v triede Minesweeper.
    Metóda na základe mena grafického rozhrania vytvorí požadovaný objekt rozhrania (návrhový vzor Factory Method).
    • Ak hodnota parametra name je rovná "swing", tak návratovou hodnotou bude objekt grafického používateľského rozhrania typu SwingUI.
    • Ak hodnota parametra name je rovná hodnote "console", tak návratovou hodnotou bude objekt používateľského rozhrania typu ConsoleUI.
    • Ak hodnota DEFAULT_UI nie je rovná ani jednej z vyššie uvedených hodnôt, tak vznikne objekt výnimky typu RuntimeException so správou "No valid UI specified".
    Úloha: Pridajte aplikáciu metódy create(DEFAULT_UI) do konštruktora triedy Minesweeper.
  7. Aktuálny model tried aplikácie je nasledujúcom obrázku.
    Obr.: : Diagram tried aplikácie Minesweeper (na konci cvičenia 10)
  8. Vymažte projekt z disku a zrušte všetky vami vytvorené nastavenia v prostredí NetBeans!

Zdroje

  1. Zdrojové kódy:

Doplňujúce úlohy

    Úloha: Implementujte voľbu typu používateľského rozhrania pomocou argumentov príkazového riadku (prepínač -swing resp. -console).
    Úloha: Dodajte podporu pre odkrývanie susedných dlaždíc pri stlačení oboch tlačidiel myši naraz.
    Úloha: Rozšírte stav dlaždice o označenie otáznikom.
comments powered by Disqus