Slevový týden - Březen C# týden
Využij náš slevový týden a získej až 30 % bodů navíc zdarma! Zároveň také probíhá C# týden se slevou na e-learning až 80 %
Hledáme fulltime programátora do ITnetwork týmu -100% homeoffice, 100% časově flexibilní #bezdeadlinu Mám zájem!

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

V minulé lekci, Upomínač narozenin v JavaFX - Návrh formuláře, jsme si v nástroji JavaFX Scene Builder navrhli hlavní formulář aplikace.

Dnes budeme v Java tutoriálu 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

Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

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ů. Vyzkoušíme si to na dialogu.

Do kontroleru si přidáme novou metodu vytvorObsahDialogu(), která bude vypadat následovně:

private void vytvorObsahDialogu(Dialog<Osoba> dialog) {
    // Vytvoření "potvrzovacího" tlačítka pro potvrzení dialogu
    ButtonType createButtonType = new ButtonType("OK", ButtonData.OK_DONE);
    // Nastavení tlačítek dialogu
    dialog.getDialogPane().getButtonTypes().setAll(createButtonType, ButtonType.CANCEL);

    // Mřížka
    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);

    dialog.setResultConverter(new Callback<ButtonType, Osoba>() {
        @Override
        public Osoba call(ButtonType param) {
            // Obsluha tlačítek dialogu
            return null;
        }
    });

    dialog.getDialogPane().setContent(grid);
}

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 nové potvrzovací tlačítko s vlastním textem. Toto tlačítko spolu s tlačítkem Cancel přidáme do dialogu.

Dále si vytvoříme GridPane, tabulkový panel, kterému nastavíme zarovnání a okraje.

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

Další řádky tvoří obsluhu události nastavení výsledku dialogu. Implementaci logiky si necháme na další lekci. Zatím budeme jednoduše vracet null.

Naplněný GridPane a tlačítko přidáme dialogu pomocí metody dialog.getDialogPane().setContent(grid).

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

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

    vytvorObsahDialogu(dialog);
    dialog.showAndWait();
}

Vytváříme zde instanci nového dialogu. Nastavíme mu titulek a velikost okna. Dále zavoláme naší výše vytvořenou metodu, pomocí které naplníme dialog vlastním obsahem. 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é.

V příští lekci, Upomínač narozenin v JavaFX - Logická vrstva, 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 683x (173.1 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?
11 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 - Návrh formuláře
Všechny články v sekci
Okenní aplikace v Java FX
Miniatura
Následující článek
Upomínač narozenin v JavaFX - Logická vrstva
Aktivity (5)

 

 

Komentáře

Avatar
luksar12
Člen
Avatar
luksar12:27.3.2014 16:59

Aplikace nejede, kvůli příkazu:
grid.setPadding(new Insets(10));
Nebere příkaz Insets a píše chybu:
grid.setPadding(new Insets(10));
required: int,int,int,int
found: int
reason: actual and formal argument lists differ in length

 
Odpovědět
27.3.2014 16:59
Avatar
luksar12
Člen
Avatar
Odpovídá na luksar12
luksar12:27.3.2014 17:11

už je to dobré, asi jsem tam něco přehlédl

 
Odpovědět
27.3.2014 17:11
Avatar
Matěj Kripner:29.3.2014 17:09

Mně to taky blblo. Jde o to nastavit ten správný import. Netbeans tam nabízí dva.

import javafx.geometry.Insets
Odpovědět
29.3.2014 17:09
Give me a deep enough pipeline, and I shall move the world.
Avatar
Odpovídá na Matěj Kripner
martinzahorsky:13.4.2014 23:01
import javafx.geometry.pos

aj

import javafx.geometry.Insets

mi blbne. Hlási mi to: cannot find symbol.

Editováno 13.4.2014 23:01
 
Odpovědět
13.4.2014 23:01
Avatar
vit-siler
Člen
Avatar
vit-siler:1.8.2014 12:43

Mám jeden dotaz - ve tvorbě formuláře mi přijde kód zbytečně dlouhý a složitý na vytvoření - přijde mi, že ve Scene Builderu by to bylo rychlejší. Jak je to v praxi? Používají programátoři spíše tento dlouhý a časově náročný zápis, nebo si to jednoduše naklikají ve Scene Builderu?

 
Odpovědět
1.8.2014 12:43
Avatar
-snaživec-
Člen
Avatar
-snaživec-:17.10.2014 15:07

Dá sa vytvoriť okno bez možnosti zatvorenia?

Odpovědět
17.10.2014 15:07
Pomali ďalej zájdeš.
Avatar
Hit
Člen
Avatar
Hit:24.10.2014 18:46

K čemu slouží nastavení modality?

Odpovědět
24.10.2014 18:46
Life's not about how hard you can hit, it's about how hard you can GET hit and keep moving forward.
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Hit
David Čápka:24.10.2014 19:03

Vždyť je tam vysvětlené co je to modální okno.

Odpovědět
24.10.2014 19:03
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
Vojta
Redaktor
Avatar
Vojta:28.11.2014 20:09

Ahoj :),
když se pokouším do mřížky přiřadit label (grid.add(jme­noLabel, 0, 0);), tak mi NetBeans napíše error: "Incompatible types: label cannot be converted to Node". Neví někdo jak bych to mohl vyřešit?

 
Odpovědět
28.11.2014 20:09
Avatar

Člen
Avatar
Odpovídá na Vojta
:28.11.2014 21:17

Pravděpodobně máš naimportovaný Label z knihovny awt a ne z knihovny javafx.

 
Odpovědět
28.11.2014 21:17
Avatar
Vojta
Redaktor
Avatar
Odpovídá na
Vojta:29.11.2014 7:15

Bylo to ono, díky moc. :)

 
Odpovědět
29.11.2014 7:15
Avatar
LukyH
Člen
Avatar
Odpovídá na vit-siler
LukyH:22.12.2014 11:55

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
Neaktivní uživatel:8.7.2015 19:48

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
Neaktivní uživatelský účet
Avatar
Petr Štechmüller
Překladatel
Avatar
Odpovídá na Neaktivní uživatel
Petr Štechmüller:8.7.2015 20:21

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
8.7.2015 20:21
Pokud spolu kód a komentář nekorespondují, budou patrně oba chybné
Avatar
Odpovědět
8.7.2015 20:27
Neaktivní uživatelský účet
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
Hanca Vondrova:14.7.2015 13:33

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:14.7.2015 14:00

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:3.9.2015 12:46

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:17.4.2016 13:11

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.4.2016 13:11
Avatar
Odpovídá na Neaktivní uživatel
Pavel Habžanský:5.6.2016 0:05

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.6.2016 0:05
Čím větší výzva, tím větší zkušenost
Avatar
Lukáš
Redaktor
Avatar
Lukáš:17.12.2016 20:42

Ahoj, postupoval jsem podle návodu, ale když kliknu na tlačítko "přidat" tak se nic nestane můj OsobaDialog vypadá takto http://www.itnetwork.cz/dev-lighter/831 a controller http://www.itnetwork.cz/dev-lighter/830 kde jsem udělal chybu? Díky za pomoc

Lukáš

 
Odpovědět
17.12.2016 20:42
Avatar
Vítězslav Dvořák:22.1.2017 16:40

u toho Insets(10) mi NetBeans hlásí "constructor Insets in class Insets cannot by applied to given types" nemůžu přojít na to, co s tím :-( ...jinak mám vše přesně jak tady v článku

 
Odpovědět
22.1.2017 16:40
Avatar
Petr Štechmüller
Překladatel
Avatar
Odpovídá na Vítězslav Dvořák
Petr Štechmüller:22.1.2017 17:00

Ahoj, zjisti si, odkud máš třídu Insets naimportovanou. Podle tvého probému to vypadá, že jsi si to naimportoval z balíčku java.awt.insets který má pouze jeden konstruktor.
Take řešení bude upravit import na toto: javafx.geometry­.Insets

Odpovědět
22.1.2017 17:00
Pokud spolu kód a komentář nekorespondují, budou patrně oba chybné
Avatar
Lesní Muž
Člen
Avatar
Odpovídá na Lukáš
Lesní Muž:10.3.2017 16:38

Kód je dobře, jede mi. Pravděpodobně jsi zapomněl přiřadit tlačítkům obslužné metody v JavaFX Scene Builderu.
Edit: Jejda, tys to psal 17. 12. 2016, už jsi na to asi přišel. Kdyžtak mi dej vědět, jestli to tak opravdu bylo :D.

Editováno 10.3.2017 16:41
 
Odpovědět
10.3.2017 16:38
Avatar
David
Člen
Avatar
David:14.7.2017 22:51

Ahoj, pro všechny, kterým tento kód nefunguje. Zkuste nechat závorky za OsobaDialog prázdné a vynechat řádek: initOwner(okno); . Netuším proč to tak je, ale po hodině zkoušení mi to tak začalo fungovat. ;)
PS: Chtělo by to update článku.

 
Odpovědět
14.7.2017 22:51
Avatar
filipfr
Člen
Avatar
filipfr:9.2.2018 13:20

Ahoj, jaktože v konstruktoru mohu použít nestatickou metodu vytvorScenu()? Dle mých dosavadních poznatků by to jít nemělo. Děkuji

 
Odpovědět
9.2.2018 13:20
Avatar
IWontTellYou
Člen
Avatar
IWontTellYou:28.5.2018 13:04

Mám tu problém s týmto gridom. Nechce mi tam pridať object typu Label. Snažil som sa na to prísť ale neviem prečo to tak je. Pravdepodobne som tam dačo zle napísal a teraz to nejde tak skúste niekto pozrieť o čo tam ide.

Ďakujem :)

 
Odpovědět
28.5.2018 13:04
Avatar
IWontTellYou
Člen
Avatar
Odpovídá na IWontTellYou
IWontTellYou:28.5.2018 13:06

Prikladám aj importované triedy

 
Odpovědět
28.5.2018 13:06
Avatar
IWontTellYou
Člen
Avatar
Odpovídá na IWontTellYou
IWontTellYou:28.5.2018 13:17

Okej tak som na to prišiel, mal som tam import na awt namiesto scene :/

 
Odpovědět
28.5.2018 13:17
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 29 zpráv z 29.