NOVINKA - Online rekvalifikační kurz Java programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

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

V minulé lekci, Upomínač narozenin v JavaFX - Logická vrstva, jsme dokončili základ logické vrstvy aplikace.

Dnes si v JavaFX tutoriálu propojíme logickou vrstvu s formulářem a naši 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 dvě vrstvy se v aplikaci striktně oddělují, jelikož jinak je kód velmi nepřehledný. 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ě.

Nikdy bychom neměli provádět výpočty, zápisy do souborů či databáze a podobné věci přímo v kontroleru formuláře!

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á část 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ě.

Úprava kontroleru

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

private final 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 do ListView nastavíme položky, které obsahuje ObservableList ze správce osob. Odteď bude ListView zobrazovat obsah naší kolekce ObservableList. Pokud se do seznamu něco přidá, projeví se to i v ListView. Pokud jsou v kolekci ObservableList nějaké osoby, nastavíme vybranou položku ListView na první index:

@Override
public void initialize(URL url, ResourceBundle rb) {
    dnesLabel.setText(Datum.zformatuj(LocalDate.now()));
    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 a upravíme připravenou obslužnou metodu dialogu. Najdeme si tedy metodu call(), která se nachází v metodě vytvorObsahDialogu(), a upravíme ji. 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:

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

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 v případě špatného zadání spadnout, použijeme try-catch blok, který případnou výjimku odchytí.

V uvedeném kódu může vyvolat výjimku řádek:

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

Je to proto, že výjimku přímo vyhazujeme v konstruktoru třídy Osoba v případě špatných údajů, tedy pokud je jméno kratší tří znaků nebo pokud uživatel zadá budoucí datum. Další výjimku může vyvolat i parsování data, 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 části try. V části 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.

Doplnění obslužných metod tlačítek

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);
    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í zkusíme načíst. Pokud tam nějaká je, přidáme osobu do správce. Uživatel totiž může dialog jednak odeslat, tedy potvrdit tlačítkem OK, ale také ho může pouze zavřít křížkem. 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. Vidíme, že se k vybrané položce dostaneme pomocí metody getSelectedItem(), kterou voláme na SelectionModel. Získanou osobu předáme metodě odeber() na správci, která dále vykoná fyzické odebrání z kolekce ObservableList.

Aplikaci si nyní vyzkoušejme, 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 se tedy nyní zobrazuje jejich jméno:

Přidávání a odebírání položek v ListView v JavaFX - Java FX - Okenní aplikace

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.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 679x (11.17 kB)
Aplikace je včetně zdrojových kódů v jazyce Java

 

Předchozí článek
Upomínač narozenin v JavaFX - Logická vrstva
Všechny články v sekci
Java FX - Okenní aplikace
Přeskočit článek
(nedoporučujeme)
Upomínač narozenin v JavaFX - Dokončení logiky
Článek pro vás napsal David Hartinger
Avatar
Uživatelské hodnocení:
18 hlasů
David je zakladatelem ITnetwork a programování se profesionálně věnuje 15 let. Má rád Nirvanu, nemovitosti a svobodu podnikání.
Unicorn university David se informační technologie naučil na Unicorn University - prestižní soukromé vysoké škole IT a ekonomie.
Aktivity