Vajíčková mánie Vajíčková mánie
Probíhá výprodej HTML, JavaScript a Bootstrap. Slevy až 80 %
Vyšlehej si extra vědomosti! Až 100% bodů na prémiový obsah zdarma! Více zde

Lekce 7 - Upomínač narozenin v JavaFX - Propojení vrstev

Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem.
Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulé lekci, Upomínač narozenin v JavaFX - Logická vrstva, jsme dokončili základ logické vrstvy aplikace. Dnes ji v Java tutoriálu propojíme s formulářem a aplikaci tak zprovozníme.

Propojení prezentační a logické vrstvy

Nyní máme dokončenou tzv. prezentační část aplikace (formulář) a logickou část (třídy). Tyto 2 vrstvy se v aplikaci striktně oddělují, jelikož jinak je kód velmi nepřehledný. Nikdy byste neměli provádět výpočty, zápisy do souborů, databáze a podobné věci přímo v kontroleru formuláře! Vždy si vytvoříme třídu, která poskytuje příslušné metody a tuto třídu z kontroleru pouze používáme. Logika zůstane ve třídě. Třída by naopak vůbec neměla vědět o formuláři. Neměla by tedy např. zobrazovat chybové hlášky, ale pouze vyhazovat v případě chyby výjimky. Je potom na formuláři, aby uživateli chybu zobrazil. Právě formulář je ta část aplikace, která s uživatelem komunikuje. Žádná jiná to nedělá.

Pokud vás napadlo, že naše jednoduchá kalkulačka, kterou jsme vytvořili v prvních dílech seriálu, byla návrhově špatně, máte pravdu. Z důvodu jednoduchosti jsme napsali výpočty rovnou do obslužné metody tlačítka. Správně bychom měli mít nějakou třídu, která by výsledky počítala a tu bychom z formuláře pouze volali.

Ukážeme si tedy, jak se to dělá správně.

Propojení prezentace a logiky

Přejdeme do kontroleru formuláře a třídě přidáme privátní atribut typu SpravceOsob, ve kterém rovnou vytvoříme instanci správce:

private SpravceOsob spravceOsob = new SpravceOsob();

Instance správce se vytvoří při vytvoření formuláře a formulář s ní dále bude komunikovat a tak provádět úkony, které si přeje uživatel.

V metodě initialize() nastavíme dnesLabel na aktuální datum a ListView nastavíme položky na ObservableList ze správce osob. Odteď bude ListView zobrazovat obsah ObservableListu a pokud se do listu něco přidá, projeví se to i v ListView. Pokud jsou v listu nějaké osoby, nastavíme vybranou položku ListView na první index.

@Override
public void initialize(URL url, ResourceBundle rb) {
    dnesLabel.setText(Datum.zformatuj(Calendar.getInstance()));
    osobyListView.setItems(spravceOsob.getOsoby());
    if (!spravceOsob.getOsoby().isEmpty())
        osobyListView.getSelectionModel().select(0);
}

Přidávání a mazání osob

Abychom něco konečně také viděli, přejdeme k přidávání osob. Přejdeme do připravené obslužné metody dialogu, ta se nachází v metodě vytvorObsahDialogu(). Zde se pokusíme vytvořit a vrátit osobu na základě údajů, které uživatel zadal. Pokud se něco nepovede, vypíšeme chybu. Jistě jste se již setkali s konstrukcí try-catch, která umožňuje odchytit vyvolané výjimky a nějak na tyto chyby reagovat místo toho, abychom nechali aplikaci spadnout.

dialog.setResultConverter(new Callback<ButtonType, Osoba>() {
    @Override
    public Osoba call(ButtonType param) {
        try {
            Calendar narozeniny = Datum.naparsuj(datumTextField.getText());
            return new Osoba(jmenoTextField.getText(), narozeniny);
        } catch (ParseException | IllegalArgumentException ex) {
            System.out.println("Chyba: " + ex.getMessage());
            Alert alert = new Alert(AlertType.ERROR, "Osobu se nepodařilo naparsovat!");
            alert.showAndWait();
            return null;
        }
    }
});

Právě řádek:

return new Osoba(jmenoTextField.getText(), narozeniny);

Může vyvolat výjimku, jelikož výjimku přímo vyhazujeme v konstruktoru osoby v případě špatných údajů, můžete se tam podívat. Další výjimku může vyvolat i parsování datumu, protože do TextFieldu může uživatel napsat prakticky cokoli a komponentu pro datum jsme nepoužili. Kód, který výjimku vyvolává, umístíme do bloku try. V bloku catch poté výjimku odchytíme a zobrazíme její zprávu uživateli. Pokud vše proběhne hladce, program se do bloku catch ani nedostane. Výjimky většinou vyvoláváme v logických třídách a potom je chytáme ve formulářích. Výjimky jsou podrobněji popsané v článku Výjimky v Javě.

Chybovou hlášku vypíšeme do konzole. Uživateli zobrazíme pěkný dialog s informací, že se osobu nepodařilo vytvořit.

V této metodě jsme skončili. Přesuneme se zpět do obslužných metod tlačítek Přidat a Odebrat a doplníme jejich kód.

@FXML
public void handlePridatButtonAction(ActionEvent event) {
    Dialog<Osoba> dialog = new Dialog<>();
    dialog.setTitle("Nová osoba");
    dialog.setWidth(350);
    dialog.setHeight(250);

    vytvorObsahDialogu(dialog);
    final Optional<Osoba> vysledek = dialog.showAndWait();
    if (vysledek.isPresent()) {
        Osoba osoba = vysledek.get();
        spravceOsob.pridej(osoba);
    }
}

V obslužné metodě tlačítka pridatButton již vytváříme novou instanci dialogu. Osobu z dialogu si nyní i načteme a pokud tam nějaká je (uživatel dialog potvrdil tlačítkem OK a neodkřížkoval ho), přidáme osobu do správce. Protože používáme ObservableList, zobrazí se osoba ihned i v ListView na formuláři.

Obslužná metoda tlačítka odebratButton bude vypadat takto:

@FXML
public void handleOdebratButtonAction(ActionEvent event) {
    Osoba vybrana = osobyListView.getSelectionModel().getSelectedItem();
    if (vybrana != null) {
        spravceOsob.odeber(vybrana);
    }
}

Důležitá je podmínka, která zjišťuje, zda je v ListView vybraná nějaká položka. Jak vidíte, k vybrané položce se dostaneme přes vlastnost getSelectedItem na SelectionModelu. Tuto osobu předáme metodě odeber na správci, která dále vykoná fyzické odebrání z ObservableListu.

Aplikaci si nyní můžete vyzkoušet, již půjde přidávat a odebírat osoby. Přidané osoby se ihned objeví v ListView díky tomu, že používáme ObservableList. ListView vždy zobrazuje to, co vrací metoda toString() objektu. U osob tedy zobrazuje jejich jméno.

Přidávání a odebírání položek v ListView v JavaFX

V příští lekci, Upomínač narozenin v JavaFX - Dokončení logiky, doplníme logickou vrstvu aplikace o další metody a tím ji dokončíme.


 

Stáhnout

Staženo 623x (182.07 kB)
Aplikace je včetně zdrojových kódů v jazyce java

 

 

Článek pro vás napsal David Čápka
Avatar
Jak se ti líbí článek?
5 hlasů
Autor pracuje jako softwarový architekt a pedagog na projektu ITnetwork.cz (a jeho zahraničních verzích). Velmi si váží svobody podnikání v naší zemi a věří, že když se člověk neštítí práce, tak dokáže úplně cokoli.
Unicorn College Autor sítě se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.
Předchozí článek
Upomínač narozenin v JavaFX - Logická vrstva
Všechny články v sekci
Okenní aplikace v Java FX
Miniatura
Následující článek
Upomínač narozenin v JavaFX - Dokončení logiky
Aktivity (6)

 

 

Komentáře
Zobrazit starší komentáře (3)

Avatar
Martin
Člen
Avatar
Martin:24.9.2014 18:32

Chtěl bych se zeptat proč se mi aplikace ve swingu spustí hned ale v FX to trvá třeba deset sekund.

 
Odpovědět 24.9.2014 18:32
Avatar
LukyH
Člen
Avatar
LukyH:27.12.2014 20:20

U metody odebratButton píšete o přetypování na typ Object. Toto se domnívám by platilo ještě před vydáním JDK5 kdy se poprvé objevila genericita. A v kontroléru přece máme:

private ListView<Osoba> osobyListView;

. Dále mi není zcela jasné použití klíčového slova final u datumTextField ve třídě OsobaDialog. To označení přece jen zajišťuje chránění příslušné (v tomto případě lokální) proměnné před dalšími změnami. Kód jsem skompiloval v Javě 8 bez jakýchkoliv problémů nebo varování. Při spuštění aplikace jsem zatím také nenarazil na problémy. Jsou snad s tímto ve starších verzích Javy problémy nebo jaké jsou důvody použití této konstrukce? Jinak pěkný článek o JavaFX.

 
Odpovědět  +2 27.12.2014 20:20
Avatar
kavalekp
Člen
Avatar
kavalekp:22.1.2015 11:15

Pro ty z vas ktery pouzivaji IntelliJ Idea, je zapotrebi v Project Structure -> Project Settings -> Molules, a nastavit Project language level na 7.0 - Diamonds, ARM, multi-catch etc. jinak catch blok v tlacitko.setO­nAction neprojde.

 
Odpovědět 22.1.2015 11:15
Avatar
roman64
Redaktor
Avatar
roman64:14.7.2015 14:40

Mám problém. OsobaDialog:
catch (ParseException | IllegalArgumen­tException ex) Netbeans mi píše že mám odstranit (remove) klauzuly **ParseException ** (import java.text.Par­seException; proveden). Hlásí to jako trvdou chybu se žárovkou. Pak neodchytne, když je chyba na parse. Chyby z Osoba (krátké jmné a budoucí datum odchytne). V čem by mohla být příčina? Celý zdroják :
http://www.itnetwork.cz/dev-lighter/619

Editováno 14.7.2015 14:43
Odpovědět 14.7.2015 14:40
opravdu chytrý člověk se učí celý život
Avatar
Petr Štechmüller
Překladatel
Avatar
Odpovídá na roman64
Petr Štechmüller:14.7.2015 14:49

Zkuste nahradit

ParseException | IllegalArgumentException

jenom za obyčejnou vyjímku

Exception

pak by to mělo fungovat určitě...

Odpovědět  +1 14.7.2015 14:49
Pokud spolu kód a komentář nekorespondují, budou patrně oba chybné
Avatar
roman64
Redaktor
Avatar
roman64:14.7.2015 21:21

Exception zafungoval :-) . Dík. příčina asi bude v použité mětodě parsování datumu. Používám novou třídu LocalDate a tuto notaci: LocalDate datumNarozeniny = LocalDate.par­se(datumNaroze­niTextField.get­Text(), DateTimeFormat­ter.ofLocalized­Date(FormatSty­le.MEDIUM));. To by vysvětlovalo i skutečnost, že v případě otevření "Upominacnaro­zenin4.zip" Netbeans nenutí ParseException odstranit (neb je tam použitá jiná metoda parsování).

Odpovědět 14.7.2015 21:21
opravdu chytrý člověk se učí celý život
Avatar
petr.fiala
Člen
Avatar
petr.fiala:9.7.2016 15:29

děkuji za pěkný přehledný tutoriál. Zajímalo by zda jsem správně odpozoroval, že v případě, kdy vytváříme nové okno čistě pomoci Javy (OsobaDialog) v podstatě view a controller spojujeme do jedné třídy?

 
Odpovědět 9.7.2016 15:29
Avatar
pocitac770
Redaktor
Avatar
Odpovídá na petr.fiala
pocitac770:9.7.2016 15:44

Nevím, co myslíš v tuto chvíli pojmem "View", ale tím spojením máš víceméně pravdu. FXML je pouhé zjednodušení FX, které umožňuje automaticky vykonat určité kusy kódu (které jsme si ručně definovali na příkladu v OsobaDialog) s pomocí XML souboru, kde jsou použité vlastnosti (velikosti, obsah, propojovací metody) definovány. Sice to tu nebylo ukázáno, ale i s pomocí FXML jde vytvořit více oken najednou propojených logikou, jako bylo u zdejšího příkladu.

Editováno 9.7.2016 15:45
 
Odpovědět  +1 9.7.2016 15:44
Avatar
Jan Novák
Člen
Avatar
Jan Novák:14. dubna 23:19

Zdravím.
Mohl bych v "ListView" vypsat místo jmen např. data narození?
Děkuji.

 
Odpovědět 14. dubna 23:19
Avatar
Jan Novák
Člen
Avatar
Odpovídá na Jan Novák
Jan Novák:15. dubna 0:42

Mno, to možná trochu předbíhám.
Z nějakého důvodu mi "ListView" místo jmen ukazuje nejspíš označení jednotlivých prvků (místo "Karel" se zobrazuje "nazev_projek­[email protected]­ny_cislo"). Může mi někdo poradit co s tím?

 
Odpovědět 15. dubna 0:42
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 13. Zobrazit vše