Ciele
- Oboznámiť sa s tvorbou grafického používateľského rozhrania.
- Oboznámiť sa s udalosťami riadeným vykonávaním programu.
- 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
-
Pridajte do triedy
Minesweeper
nasledujúcu metódu. Táto metóda sa bude používať pre začatie hrania novej hry.
Teraz ju možete použiť v konštruktorepublic void newGame() { Field field = new Field(setting.getRowCount(), setting.getColumnCount(), setting.getMineCount()); startMillis = System.currentTimeMillis(); userInterface.newGameStarted(field); }
Minesweeper
na začatie prvej hry. -
V nasledujúcom kroku pridajte do projektu Minesweeper triedy pre grafické používateľské rozhranie.Úloha: Pridajte do projektu (do adresáraArchív obsahuje adresár
src
) obsah archívu swingui.zip.img
s obrázkami a balíkminesweeper.swingui
. V balíkuminesweeper.swingui
sú triedyTileComponent
aSwingUI
. Oboznámte sa s triedamiTileComponent
aSwingUI
.-
Trieda
TileComponent
je grafický komponent slúžiaci pre vykreslenie jednej dlaždice hracieho poľa. -
Trieda
SwingUI
predstavuje okno hry a zároveň implementuje rozhranieUserInterface
.
-
Trieda
-
Nasledujúcim krokom je zobrazenie hracej plochy v okne aplikácie.Úloha: Implementujte metóduV rámci tejto metódy je potrebné vykonať nasledujúce kroky:
public void newGameStarted(Field field)
triedySwingUI
.-
Inicializovať premennú objektu
field
argumentom metódynewGameStarted(Field field)
. -
Odstrániť všetky komponenty, ktoré obsahuje panel
contentPanel
prostredníctvom volaniacontentPanel.removeAll()
(Komponenty sa odstraňujú z dôvodu vytvorenia nového hracieho poľa). Nastavte pre panelcontentPanel
manažér rozmiestnenia na typGridLayout
prostredníctvom aplikáciecontentPanel.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ódyComponent 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óduvoid addMouseListener(MouseListener l)
. TriedaSwingUI
implementuje rozhranieMouseListener
.public class SwingUI extends JFrame implements UserInterface, MouseListener {...}
-
Aplikovať metódu
update()
triedySwingUI
pre zobrazenie počiatočného stavu hracieho poľa. -
Aplikovať metódu
pack()
triedySwingUI
zabezpečujúcu rozloženie komponentov hlavného okna hry Minesweeper s cieľom minimalizácie veľkosti okna (kompaktný tvar).
Úloha: Implementujte metódupublic void update()
triedySwingUI
. V tejto metóde je nutné nad každým grafickým komponentom triedyTileComponent
aplikovať metóduupdateStyle()
. Taktiež je potrebné aktualizovať počítadlo zostávajúcich neoznačených mín aplikovaním metódysetMinesLeftLabelText()
triedySwingUI
. -
Inicializovať premennú objektu
-
Ďalším krokom je definovanie spracovania udalosti nad dlaždicami hracej plochy hry Minesweeper.Úloha: Implementujte metóduVykonanie tejto metódy je určené nasledujúcimi krokmi:
public void mousePressed(MouseEvent e)
triedySwingUI
. Táto metóda je implementáciou reakcie na stlačenie tlačidla myši nad grafickým komponentom triedyTileComponent
.-
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 triedyField
. Pozícia grafického komponentu dlaždice v hracom poli je prístupná v objekte grafického komponentuTileComponent
.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óduisLeftMouseButton(MouseEvent e)
triedySwingUtilities
. -
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óduvoid showMessageDialog(Component parentComponent, Object message, String title, int messageType)
triedyJOptionPane
. -
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ódyvoid addPlayerTime(String name, int time)
triedyBestTimes
. Pre získanie času hrania hry použite metódugetPlayingSeconds()
objektu triedyMinesweeper
. Pre získanie mena používateľa použite výrazSystem.getProperty("user.name")
, ktorý poskytne hodnotu systémovej premennej prostrediauser.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 triedyField
.Pre identifikovanie stlačenia pravého tlačidla myši použite statickú metódu
isRightMouseButton(MouseEvent e)
triedySwingUtilities
. -
Po vykonaní odkrytia resp. označenia dlaždice je potrebné prekresliť hracie pole aplikovaním metódy
update()
triedySwingUI
.
-
Podmienkou reakcie na stlačenie myši je stav hry
-
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:
-
Vytvorte triedu
BestTimesDialog
typuJDialog
(„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ódygetBestTimes()
nad objektom triedyMinesweeper
. Informácie o časoch zobrazte do grafického prvkuJTextArea
(pomocou metódyvoid setText(String t)
).Poznámka: Pre vycentrovanie dialógového okna nad oknom hracej plochy použite metódusetLocationRelativeTo(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ázvomokButton
, tak metóda bude vygenerovaná v nasledujúcej forme:
Implementujte spracovanie udalosti pre stlačenie tlačidla nasledovne:private void okButtonActionPerformed(java.awt.event.ActionEvent evt) { // TODO add your handling code here: }
Daný kód zatvorí dialógové okno a uvoľní zdroje späté s oknom.setVisible(false); dispose();
-
V triede
SwingUI
dodajte implementáciu stlačenia menu „Game > Best Times...”. Na vyhľadanie položky menubestTimesMenuItem
použite okno „Inspector”. Postupujte podľa postupu uvedenom hore. Implementácia reakcie na udalosť je nasledovná.new BestTimesDialog(this, true).setVisible(true);
-
Vytvorte triedu
-
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
, aleboConsoleUI
).Úloha: Implementujte metóduMetóda na základe mena grafického rozhrania vytvorí požadovaný objekt rozhrania (návrhový vzor Factory Method).private UserInterface create(String name)
v triedeMinesweeper
.-
Ak hodnota parametra name je rovná "
swing
", tak návratovou hodnotou bude objekt grafického používateľského rozhrania typuSwingUI
. -
Ak hodnota parametra name je rovná hodnote "
console
", tak návratovou hodnotou bude objekt používateľského rozhrania typuConsoleUI
. -
Ak hodnota
DEFAULT_UI
nie je rovná ani jednej z vyššie uvedených hodnôt, tak vznikne objekt výnimky typuRuntimeException
so správou "No valid UI specified".
Úloha: Pridajte aplikáciu metódycreate(DEFAULT_UI)
do konštruktora triedyMinesweeper
. -
Ak hodnota parametra name je rovná "
-
Vymažte projekt z disku a zrušte všetky vami vytvorené nastavenia v prostredí NetBeans!
Zdroje
- 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.
TileComponent
sú uložené priamo v panelicontentPanel
. Prechádzať prvkami môžete prostredníctvom metódcontentPanel.getComponentCount()
acontentPanel.getComponent(index)
.