4. díl - Upomínač narozenin v JavaFX - Formuláře podruhé

Java JavaFX Upomínač narozenin v JavaFX - Formuláře podruhé

V minulém dílu našeho seriálu tutoriálů o JavaFX jsme si v nástroji JavaFX Scene Builder navrhli hlavní formulář aplikace. Dnes budeme s formuláři pokračovat.

V projektu bude figurovat třída Osoba, proto si ji k němu přidáme a zatím ji ponecháme prázdnou.

public class Osoba
{
}

Příprava kontroleru

Přejděme do kontroleru formuláře a vytvořme atributy s @FXML anotací pro komponenty formuláře, které budeme z kódu používat. Rovnou si připravme i obslužné metody. Náš kontroler bude vypadat asi takto:

public class FXMLDocumentController implements Initializable {

    @FXML
    private ListView<Osoba> osobyListView;
    @FXML
    private Label dnesLabel;
    @FXML
    private Label nejblizsiLabel;
    @FXML
    private Label narozeninyLabel;
    @FXML
    private Label vekLabel;

    @FXML
    public void handlePridatButtonAction(ActionEvent event) {

    }

    @FXML
    public void handleOdebratButtonAction(ActionEvent event) {

    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // TODO
    }

}

Pracovat budeme s ListView a potom se čtyřmi Labely (to jsou ty, které mají na formuláři v textu otazník). Zbytek komponent nebudeme v kontroleru potřebovat a je proto zbytečné si je ukládat. Dále zde máme připravené obslužné metody pro obě tlačítka.

Propojení kontroleru a FXML

Změny v souboru uložte a přejděte do JavaFX Scene Builderu, kde ListView a čtyřem Labelům nastavte příslušná fx:id. Tlačítkům nastavte obslužné metody, jako jsme to dělali u kalkulačky. Nastavovat fx:id jim nemusíme.

Nastavení fx id v JavaFX Scene Builderu

Pozn.: U obslužných metod tlačítek můžeme parametr ActionEvent vynechat. Standardně se tam však uvádí, i když ho zrovna nevyužijeme.

Dialog

V aplikaci budeme dále kromě hlavního formuláře potřebovat dialog pro vytvoření nové osoby. Dialog bude vypadat takto:

Diloag v JavaFX

Formulář je opravdu jednoduchý. Obsahuje pouze dva TextFieldy a Button. Při úvodu do JavaFX jsme si říkali, že kromě FXML a JavaFX Scene Builderu můžeme formulář vytvořit i jako instance objektů. U tohoto formuláře si to vyzkoušíme.

K projektu si přidáme novou třídu se jménem OsobaDialog, kterou oddědíme od Stage.

public class OsobaDialog extends Stage {

}

Vytvoření scény

Třídě nejprve dodáme metodu k vytvoření scény. Bude vypadat následovně:

private Scene vytvorScenu() {
        VBox box = new VBox();
        box.setAlignment(Pos.CENTER);
        box.setSpacing(20);

        // Mřížka s TextFieldy a Labely
        GridPane grid = new GridPane();
        grid.setAlignment(Pos.CENTER);
        grid.setPadding(new Insets(10));
        grid.setHgap(10);
        grid.setVgap(10);

        // Komponenty
        TextField jmenoTextField = new TextField();
        TextField datumTextField = new TextField();
        Label jmenoLabel = new Label("Jméno");
        Label datumLabel = new Label("Datum narození");

        grid.add(jmenoLabel, 0, 0);
        grid.add(jmenoTextField, 1, 0);
        grid.add(datumLabel, 0, 1);
        grid.add(datumTextField, 1, 1);

        // Tlačítko
        Button tlacitko = new Button("OK");
        tlacitko.setOnAction(new EventHandler<ActionEvent>() {
                @Override public void handle(ActionEvent e) {
                        // Obsluha tlačítka
                }
        });

        box.getChildren().addAll(grid, tlacitko);
        return new Scene(box);
}

Metoda dělá v podstatě to, co za nás jinak dělá JavaFX Scene Builder. Tento přístup se u JavaFX také používá, čili když si ho teď popíšeme, budete schopni porozumět dalším JavaFX aplikacím, které FXML z nějakého důvodu nevyužívají.

Na začátku si vytvoříme VBox, kterému nastavíme zarovnání a okraje. Následně vytvoříme GridPane, který opět nastavíme podobným způsobem.

Vytvoříme si komponenty, které naskládáme no buněk GridPane. Uvedeme vždy komponentu, sloupec a řádek, do kterého ji chceme vložit.

Další řádky vytvoří tlačítko a přiřadí mu rovnou i obslužnou metodu, která je zatím prázdná. Pro události v Javě se používá tzv. anonymní třída, pokud jste na ni ještě nenarazili. Anonymní třída zde implementuje rozhraní EventHandler a obsahuje jednu metodu handle(), která se spustí ve chvíli, kdy událost nastane.

Naplněný GridPane a tlačítko přidáme do VBoxu pomocí metody addAll(). Musíme si nejprve získat kolekci komponent ve VBoxu, do které je přidáme. Těmto komponentám se říká child (děti), VBox je jejich rodič (parrent), jelikož jsou v něm obsažené.

Nakonec vytvoříme novou scénu z VBoxu, kterou vrátíme.

Třídě OsobaDialog přidáme následující konstruktor:

public OsobaDialog(Window okno) {
        setTitle("Nová osoba");
        setWidth(350);
        setHeight(250);

        initStyle(StageStyle.UTILITY);
        initModality(Modality.WINDOW_MODAL);
        initOwner(okno);
        setScene(vytvorScenu());
}

Konstruktor bere v parametru instanci Window. Tu později získáme z libovolné komponenty hlavního formuláře. Jevišti (Stage) nastavíme titulek a rozměry. Následujících několik řádek nastaví scénu jako tzv. modální okno. To je charakterem pomocný formulář, který se zobrazí přes hlavní okno. Nakonec jevišti nastavíme scénu na tu, kterou jsme před chvílí vytvořili.

Dialog, který jsme vytvořili, by se mohl používat i pro editaci, ale tu v naší aplikaci zanedbáme, už tak ji budeme programovat ještě několik dílů.

Abychom z té práce vůbec něco viděli, přesuneme se do kontroleru a upravíme obslužnou metodu přidávacího tlačítka do následující podoby:

@FXML
public void handlePridatButtonAction(ActionEvent event) {
        OsobaDialog dialog = new OsobaDialog(dnesLabel.getScene().getWindow());
        dialog.showAndWait();
}

Vytváříme zde instanci našeho dialogu. Instanci Window získáme např. z nějakého labelu pomocí metod .getScene().get­Window(). Dialog nakonec zobrazíme metodou showAndWait(). Tím zajistíme, že hlavní okno nebude reagovat do té doby, než se dialog uzavře. U dialogu se toto většinou dělá, již jen proto, aby si uživatel nemohl ten samý dialog vyvolat vícekrát. I když nám by v podstatě nevadilo, kdyby uživatel během zadávání nové osoby aplikaci používal a otevřel třeba další dialog k zadávání nové osoby.

Aplikaci můžeme spustit a kliknout na tlačítko Přidat:

Modální dialog v JavaFX

Tím máme tedy formuláře hotové, příště se pustíme do samotné logiky aplikace. Dnešní projekt je se zdrojovými kódy jako vždy ke stažení níže.


 

Stáhnout

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

 

  Aktivity (1)

Článek pro vás napsal David Čápka
Avatar
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 se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.

Jak se ti líbí článek?
Celkem (6 hlasů) :
4444 4


 



 

 

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

Avatar
Vojta
Redaktor
Avatar
Vojta:

Bylo to ono, díky moc. :)

 
Odpovědět 29.11.2014 7:15
Avatar
LukyH
Člen
Avatar
LukyH:

Nejsem profesionál ale řekl bych, že se to v praxi víc kliká než píše - výsledek návrhu je vidět okamžitě, obsah je oddělen od logiky, tudíž vývoj funkční části a designu může probíhat paralelně, tj. další úspora času (a na tu se hraje především).

 
Odpovědět 22.12.2014 11:55
Avatar
David Šimák:

Proč musí být při vytvoření dialogu
OsobaDialog dialog = new OsobaDialog(dnes­Label.getScene()­.getWindow());
to dnesLabel?

 
Odpovědět 8.7.2015 19:48
Avatar
Odpovídá na David Šimák
Petr Štechmüller:

Protože třída OsobaDialog potřebuje ve svém konstruktoru referenci na Window aby se mohla vykreslit. Dneska se už takovéto konstrukce dělat nemusejí, protože od Javy verze 8_40 máme dialogy přímo v API, takže je s nimi lepší práce. Chtělo by to možná nějaký update...

Odpovědět  +1 8.7.2015 20:21
Pokud spolu kód a komentář nekorespondují, budou patrně oba chybné
Avatar
Hanca Vondrova:

Ahoj, mám v Scene Builderu vytvořeny dvě scény, jednu hlavní a druhé bude okno pro zadání PIN. Jakým způsobem z té hlavní scény otevřu po stisku tlačítka tu druhou? Díky

 
Odpovědět 14.7.2015 13:33
Avatar
vajkuba1234
Člen
Avatar
Odpovídá na Hanca Vondrova
vajkuba1234:

Založ si topic na fóru a tam ti odpovím. Na fóru to může pomoci i dalším. :)

Odpovědět 14.7.2015 14:00
No hope, no future, JUST WAR! For world peace Israel must be DESTROYED!
Avatar
Roman
Člen
Avatar
Roman:

Pekne všetko vysvetlené, všetko funguje nie o čom super veľká poklona autorovi :)) len škoda že takých tutorialov v CZ na JavaFX nie je viacej ale časom sa to možno zmení :)

 
Odpovědět 3.9.2015 12:46
Avatar
Tomáš Svatek:

Ahoj, děkuji za velmi dobře vysvětlený tutoriál.

Mám dotaz ohledně vytváření formulářů.

Pokud je budu vytvářet jako instance objektů, budu jich potřebovat vytvořit více podobného typu a budu chtít vytvářet stejné komponenty jako VBox a GridPane, byl by dobrý přístup vytvořit si statickou třídu ve které by byli metody, které vytvářejí tyto komponenty (které se často používají)? Používal bych je při vytváření nového formuláře v metodě vytvorScenu(), samozřejmě za předpokladu, že bych potřeboval vytvořit více podobných formulářů, kterým bych chtěl dodat podobný vzhled.

Jde mi o to jestli je to dobrý přístup z hlediska návrhu.

Děkuji za odpověd.

 
Odpovědět 17. dubna 13:11
Avatar
Odpovídá na David Šimák
Pavel Habžanský:

Podle toho, co jsem si teď na rychlo vygooglil v dokumentacích, tak bys tam místo dnesLabel mohl mít jakoukoliv komponentu na hlavním okně... Jde jen o to, aby získal instanci okna (Window), která je vstupním argumentem metody OsobaDialog(). dnesLabel.get­Scene() vrací Scene a tutý Scene se zavolá getWindow().

Odpovědět 5. června 0:05
Čím větší výzva, tím větší zkušenost
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 20. Zobrazit vše