Lekce 2 - Jednoduchá kalkulačka v JavaFX

Java JavaFX Jednoduchá kalkulačka v JavaFX

ONEbit hosting 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, Úvod do JavaFX, jsme si vysvětlili standardní HelloWorld projekt v NetBeans. Dnes si v Java tutoriálu vytvoříme svou první vlastní aplikaci v JavaFX, bude to jednoduchá kalkulačka.

Založte si nový projekt s názvem KalkulackaFX. Rovnou si ukažme, jak bude naše výsledná aplikace vypadat:

Kalkulačka v JavaFX

Návrh formuláře

Aplikaci započneme návrhem formuláře. Otevřeme FXMLDocument.fxml v JavaFX Scene Builderu a z formuláře odstraníme Button a Label.

Na prázdný formulář natahneme následující komponenty z Library.

TextField

Jak asi tušíte, TextField slouží k zadávání textu. My ho využijeme i k zadání čísel. Na formulář ho vložíme 2x.

ComboBox

ComboBox je rozbalovací nabídka, která nám umožňuje vybrat z několika předdefinovaných hodnot. Nám poslouží k výběru početní operace (sčítání, odčítání, násobení, dělení).

Label

Textové popisky budeme potřebovat dva. Jeden pro znak "rovná se" a druhý pro výsledek, který kalkulačka vypočítala. Labelům v Properties nastavte text na "=" a "0".

Button

Na formulář vložíme poslední komponentu, kterou bude tlačítko. Nastavíme mu text na "Vypočítej".

Provázání kontroleru a FXML

Přesuneme se do java kontroleru. V kódu budeme potřebovat načíst hodnoty z textových polí a vybranou položku z ComboBoxu. Také budeme potřebovat vypsat výsledek do labelu a reagovat na kliknutí na tlačítko. Z toho vyplývá, že v kontroleru potřebujeme s těmito komponentami pracovat. Založíme si pro ně ve třídě tedy atributy s anotací @FXML. Anotace musí být opravdu nad každým atributem. Zároveň si ve třídě připravíme obslužnou metodu pro naše tlačítko. Třída kontroleru bude vypadat asi takto:

public class FXMLDocumentController implements Initializable {

    @FXML
    private TextField cislo1TextField;
    @FXML
    private TextField cislo2TextField;
    @FXML
    private ComboBox operaceComboBox;
    @FXML
    private Button vypocitejButton;
    @FXML
    private Label vysledekLabel;

        @FXML
    private void handleVypocitejButtonAction(ActionEvent event) {
        }

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

}

Původní label a tlačítko s obslužnou metodou jsme ze třídy odstranili. Kód si v NetBeans uložte a přesuňte se do JavaFX Scene Builderu. Jednotlivým komponentám na formuláři přiřadíme jejich fx:id podle toho, jak jsme si pojmenovali atributy v kontroleru. Celkem tedy přiřadíme 5 fx:id. U tlačítka nesmíme zapomenout přiřadit i obslužnou metodu.

Formulář kalkulačky v JavaFX Scene Builderu

JavaFX Scene Builder pracuje s java kódem kontroleru. Pokud zadáme název neexistujícího atributu, upozorní nás na to chybovou hláškou. Javovský kód samozřejmě musí být uložený, jinak to nemá šanci poznat. To je bohužel nevýhoda toho, že se aplikace tvoří ve dvou různých nástrojích.

Obsluha formuláře

Konečně máme vše připraveno k tomu, abychom se mohli věnovat samotné obsluze formuláře.

Naplnění ComboBoxu

Jako první budeme potřebovat nějaké položky do ComboBoxu. Proto upravíme inicializační metodu kontroleru do následující podoby:

@Override
public void initialize(URL url, ResourceBundle rb) {
        ObservableList<String> operace = FXCollections.observableArrayList("+", "-", "*", "/");
        operaceComboBox.setItems(operace);
        operaceComboBox.getSelectionModel().selectFirst();
}

Nejprve vytvoříme kolekci položek. V JavaFX se pracuje s tzv. observable collections, což by se dalo přeložit jako pozorovatelné kolekce. Jakmile použijeme ObservableArrayList a nastavíme ho jako zdroj dat nějaké komponentě formuláře, tato komponenta si svůj obsah sama aktualizuje podle toho, jak se kolekce mění. Tomuto chování se někdy říká binding a ušetří nám spoustu starostí a kódu, který bychom jinak museli pro obnovování formulářů napsat. V našem případě sice položky měnit nebudeme, nicméně komponenty v JavaFX jsou implementované tak, že pracují s observable kolekcemi. Ještě dodám, že se kolekce vytvářejí pomocí továrních (statických) metod na třídě FXCollections.

Nastavení položek pomocí metody setItems() je triviální. Aby byla po spuštění aplikace hned vybraná první položka (sčítání), musíme si získat tzv. selectionModel(), který se stará o vybrané položky a na tom vybranou položku nastavit.

Obsluha tlačítka

Zbývá již jen naprogramovat obslužnou metodu tlačítka. Její kód bude následující:

@FXML
private void handleVypocitejButtonAction(ActionEvent event) {
        double cislo1 = Double.parseDouble(cislo1TextField.getText());
        double cislo2 = Double.parseDouble(cislo2TextField.getText());
        String operace = (String)operaceComboBox.getSelectionModel().getSelectedItem();
        double vysledek = 0;
        switch (operace)
        {
                case "+":
                        vysledek = cislo1 + cislo2;
                        break;
                case "-":
                        vysledek = cislo1 - cislo2;
                        break;
                case "*":
                        vysledek = cislo1 * cislo2;
                        break;
                case "/":
                        if (cislo2 != 0)
                        vysledek = cislo1 / cislo2;
                        break;
        }
        vysledekLabel.setText(String.valueOf(vysledek));
}

Jako první si naparsujeme čísla z obou TextFieldů. Text získáme metodou getText(), vyjímky při parsování pro zjednodušení nebudeme ošetřovat.

Získání vybrané operace provedeme opět přes SelectionModel, přes metodu getSelectedItem(), která vrací vybranou položku v ComboBoxu. Položku musíme přetypovat na String. Podobně bychom mohli využít metodu getSelectedIndex(), která vrátí číselný index vybrané položky. Získávání přímo objektů je však velmi praktické, v ComboBoxu totiž můžeme mít v pokročilejších aplikacích např. instance uživatelů. Vše si během seriálu ukážeme.

Následuje switch, který podle operace vypočítá výsledek. Všimněte si ošetření dělení nulou. Ideálně bychom při dělení nulou měli zobrazit nějakou chybovou hlášku. JavaFX bohužel zatím tuto funkcionalitu stále neobsahuje a musí se obcházet, což si ukážeme v dalších dílech seriálu.

Již nezbývá nic jiného, než nastavit výsledek příslušnému labelu. Samozřejmě ho musíme nejprve převést na String. Můžeme se těšit z hotové aplikace.

Distribuce

Na závěr si řekněme, jak aplikaci šířit. V NetBeans je vedle tlačítka Play tlačítko Clean and Build Project (shift + F11). Po jeho stisknutí se ve složce s vaším projektem vytvoří složka dist a v ní spustitelný JAR s vaší aplikací. Můžete ji poslat známým a pochlubit se. Dokonce je tam i vygenerovaná HTML stránka, kde je vaše kalkulačka jako applet. Můžete si ji dát i na svůj web.

Webová aplikace v JavaFX

V příští lekci, Upomínač narozenin v JavaFX - Návrh formuláře, začneme programovat upomínač narozenin přátel. Bude se jednat o praktickou a středně pokročilou aplikaci, na které se naučíme spoustu zajímavých technik. Zdrojový kód dnešního projektu je ke stažení níže pro případ, že by vám něco nefungovalo.


 

Stáhnout

Staženo 1403x (165.25 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?
17 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.
Miniatura
Předchozí článek
Úvod do JavaFX
Miniatura
Všechny články v sekci
Okenní aplikace v Java FX
Aktivity (2)

 

 

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

Avatar
Atrament
Člen
Avatar
Atrament:15.9.2017 9:06

Nechybí ti tam 'implements Initializable'?

public class FXMLDocumentController implements Initializable {
...
 
Odpovědět 15.9.2017 9:06
Avatar
David J.
Člen
Avatar
Odpovídá na Atrament
David J.:15.9.2017 16:15

Ano problém byl opravdu v chybějícím "implements Initializable". Mockrát děkuju za pomoc.

 
Odpovědět 15.9.2017 16:15
Avatar
Filip (animátor/programator):24.9.2017 13:39

Ja scene builder nemám ale aj tak sa mi to podarilo dokončiť cez kód v FXMLDocument.FXML a funguje to!!!!

Odpovědět 24.9.2017 13:39
Nikdy sa nevzdávaj a choď si za svojim snom.......
Avatar
Odpovědět 24.9.2017 13:46
Nikdy sa nevzdávaj a choď si za svojim snom.......
Avatar
Odpovídá na Filip (animátor/programator)
Petr Štechmüller:24.9.2017 13:47

Gratuluji.
btw. scene builder není podmínkou funkčnosti. Já si všechny FXML dokumenty píšu ručně.

Odpovědět  +1 24.9.2017 13:47
Pokud spolu kód a komentář nekorespondují, budou patrně oba chybné
Avatar
Feri Laky
Člen
Avatar
Feri Laky:5.11.2017 20:08

Těším se z hotové aplikace - nemám žádné červené, nebo žltočervené kuličky, i když jsem dost věcí musel dopsat v Controlleru, koré tam v originálu nebyly - a teď spustil jsem program a ..- samotřejmě žádná okna se neobjavila, ale spousta čevených výpisů, celý román, a nakonec Build suscesfull! - no super!, opakovaně.....a teď co dál?
Je škoda, že Scene Builder není integrován do NetBeans....

 
Odpovědět 5.11.2017 20:08
Avatar
Feri Laky
Člen
Avatar
Feri Laky:5.11.2017 20:24

Zatím jsem si naprogramoval dva krátke prográmky v NetBeans na výpočet správnosti platu (srovnává s výplatní páskou) a druhý na výpočet plateb za služby ve všední dny, víkendy a svátky - (jsou odlišně placené) - a bez problémů mi fungují.
Jakmile jsem začal s tímto Builderem mám jen problémy - úžasné "urychlení a pomoc":-(( - v Delphi to šlo bleskově a bez jakýchkloi problémů - kombinace Scene Builderu a NetBeans je je neuvěřtelne komplikovaná, takže si tu kalkulačku asi udělám v obyčejném Java Source-u.....

 
Odpovědět 5.11.2017 20:24
Avatar
Michal H.
Člen
Avatar
Michal H.:4. března 8:45

Ahoj, tak přiznávám že jsem zlenivělej z práce ve VS, ale upřímě tohle mi připadá jako nejkratší cesta do pekel :D Stačí jeden překlep a máš to :) No uvídíme co bude dál :)

Měl bych jeden dotaz. Když z cmBoxu získám objekt přetypovaný na string ( a uložený jako string) tak proč mi to nejde vytisknout na konzoli natož nastavit jako text?

String o = (String)cmbOp.getSelectionModel().getSelectedItem();
System.out.println(o);
 
Odpovědět 4. března 8:45
Avatar
Odpovídá na Michal H.
Petr Štechmüller:4. března 9:52

Ahoj, a co Ti to místo toho vypíše?
Mimochodem, lepší, než přetypovávat výsledek z metody getSelectedItem() je už při definici comboboxu definovat, jaký datový typ bude obsahovat.

@FXML
private ComboBox<String> cmbOp;
Odpovědět  +1 4. března 9:52
Pokud spolu kód a komentář nekorespondují, budou patrně oba chybné
Avatar
Michal H.
Člen
Avatar
Michal H.:4. března 14:47

Ahoj, děkuji za typ a odpověď ( je to lepší takto definovat :) ). Teď jsem to vyzkoušl a problém opět mezi klávesnicí a židlí. Já zvířatko rohaté jaksi zapoměl, že ve stejné metodě se nachází i parsování TextFieldu. A jak jsem se soustředil na čistý výpis vybraného itemu, tak jsem samozřejmě TF nevyplňoval => že se to přez chybu nedostalo k vypsání :-` Njn asi to chce občas dát pauzu a nečumět do toho od páté ráno :D
Děkuji.

 
Odpovědět 4. března 14:47
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 46. Zobrazit vše