Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 4 - Java GUI

V minulé lekci, Java GUI - událost, jsme naši kalkulačku zprovoznili a vysvětlili si, jak fungují události v Javě.

Dnes si upravíme naší primitivní kalkulačku. Naučíme se hlavně nový Layout a obsluhovat více tlačítek. Výsledná kalkulačka by měla vypadat takhle:

vysledek - Java Swing bez grafického návrháře

Shrnutí

Myslím, že by neuškodilo lehké shrnutí:

Abychom vytvořili okno, vytvoříme si vlastní třídu, která dědí ze třídy JFrame. Dále naší instanci nadefinujeme různé parametry (velikost okna, defaultní operaci – zavření, viditelnost). Do okna přidáváme tzv. komponenty (tlačítka, labely, textová pole atd.). To jsou instance tříd (JLabel, JTextField …). Přidáváme je do okna metodou add. Teď pozor! Až doposud jsme je přidávali přímo do okna. To můžeme samozřejmě dělat i nadále. Problém však nastane, budeme-li chtít změnit pozadí okna. Na to existuje metoda setBackground (parametr barva). Pokud ji však přidáme přímo, nestane se nic. Musíme použít tzv. kontejner. Kontejner si můžeme představit jako papír, který vyplní celé okno. Získáme ho přes metodu getContentPane(). Pozadí pak nastavíme konejneru a budeme do něho i nadále přidávat všechny komponenty. Barvu již vytvořit umíme, nadefinujeme ji tedy na nějakou příjemnou barvičku pomocí číslic RGB. Přidáme komponenty stejně jako v předchozích dílech:

public class Gui extends JFrame{

    private JLabel labCislo1, labCislo2, labVysledek;
    private JButton butSecti, butOdecti, butVydel, butVynasob;
    private JTextField tfCislo1;
    private JTextField tfCislo2;

    public Gui()
    {
        super("Kalkulačka");

        Container con = getContentPane();
        con.setBackground(new Color(210, 244, 255));
}

GridBagLayout

FlowLayout, který jsme používali do teď, je jednoduchý, ale není moc použitelný. Mnohem mocnějším nástrojem je tzv. GridBagLayout. Okno nám rozdělí na tabulku s buňkami. K buňkám přistupujeme podle souřadnicového systému X,Y. Vytvoříme instanci třídy GridBagLayout. Další nutnou věcí je instace třídy GridBagConstraints, která slouží k určení souřadnic. Layout nastavíme stejně. Pěkné by bylo, kdyby byl mezi buňkami nějaký prostor. Toho docílíme příkazem:

GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(10, 10, 10, 10);

Znázornění pro lepší pochopení:

gbLayout - Java Swing bez grafického návrháře

Přidáme na kontejner komponenty. U každého komponentu musíme určit polohu X a Y. Další změnou je parametr metody add(). Na druhé místo přidáme objekt gbc. To nám zaručí správnost rozmístění.

labCislo1 = new JLabel("Zadejte první číslo:");
    gbc.gridx = 0;
    gbc.gridy = 0;

    con.add(labCislo1, gbc);

    tfCislo1 = new JTextField(4);
    gbc.gridx = 1;
    gbc.gridy = 0;
    con.add(tfCislo1, gbc);

    labCislo2 = new JLabel("Zadejte druhé číslo:");
    gbc.gridx = 0;
    gbc.gridy = 1;
    con.add(labCislo2, gbc);

    tfCislo2 = new JTextField(4);
    gbc.gridx = 1;
    gbc.gridy = 1;
    con.add(tfCislo2, gbc);

    butSecti = new JButton("+");
    gbc.gridx = 0;
    gbc.gridy = 2;
    con.add(butSecti, gbc);

    butOdecti = new JButton("-");
    gbc.gridx = 1;
    gbc.gridy = 2;
    con.add(butOdecti, gbc);

    butVynasob = new JButton("/");
    gbc.gridx = 0;
    gbc.gridy = 3;
    con.add(butVynasob, gbc);

    butVydel = new JButton("*");
    gbc.gridx = 1;
    gbc.gridy = 3;
    con.add(butVydel, gbc);

    labVysledek = new JLabel("Výsledek:");
    gbc.gridx = 1;
    gbc.gridy = 4;
    con.add(labVysledek, gbc);

Obsluha tlačítek

Nyní se dostáváme k samotné funkčnosti. Ke každému z tlačítek musíme přidat posluchač události z nějaké třídy, do které implementuje rozhraní ActionListeneru. Asi nás napadne, že bychom mohli vytvořit čtyři třídy. Jedna by sčítala, druhá odčítala atd., ale byl by v tom zbytečný zmatek a navíc bychom dospěli k duplicitě kódu. Proto vytvoříme jenom jednu třídu - Event. Instanci event přidáme na všechna tlačítka.

Event event = new Event();
    butOdecti.addActionListener(event);
    butSecti.addActionListener(event);
    butVydel.addActionListener(event);
    butVynasob.addActionListener(event);

Metoda actionPerformed má jako parametr instanci třídy ActionEvent. Díky ní můžeme zjistit podrobnosti o tlačítku, které jsme stiskli a s něčím je porovnat. K informaci se dostaneme přes metodu getActionComand(), kterou metodou equals() porovnáme s nápisem na tlačítku. Můžeme tedy rozlišit, které tlačítko bylo stisknuto.

public class Event implements ActionListener {

       public void actionPerformed(ActionEvent e)
       {
           if(e.getActionCommand().equals("+"))
           {

           }
           else if(e.getActionCommand().equals("-"))
           {

           }
           else if(e.getActionCommand().equals("/"))
           {

           }
           else if(e.getActionCommand().equals("*"))
           {

           }
       }

Teď se dostáváme k logice programu. Samozřejmě bychom mohli všechno nabouchat mezi “ify“, ale jelikož nejsme žádní amatéři, uděláme to hezky OOP. Vytvoříme si tedy novou třídu Vypocet. Bude vypadat takto:

public class Vypocet {

    int cislo1;
    int cislo2;

    public Vypocet(int cislo1, int cislo2)
    {
        this.cislo1 = cislo1;
        this.cislo2 = cislo2;
    }

    public int secti()
    {
        return cislo1 + cislo2;
    }

    public int odecti()
    {
        return cislo1 - cislo2;
    }

    public int vydel()
    {
        return cislo1 / cislo2;
    }

    public int vynasob()
    {
        return cislo1 * cislo2;
    }
}

Všimněme si, že dělení nulou není ošetřené. K tomu se však ještě dostaneme. Vrátíme se do metody actionPerformed, která bude vypadat následovně:

public void actionPerformed(ActionEvent e)
    {
        int cislo1 = Integer.parseInt(tfCislo1.getText());
        int cislo2 = Integer.parseInt(tfCislo2.getText());
        String text = "";

        Vypocet v = new Vypocet(cislo1, cislo2);

        if(e.getActionCommand().equals("+"))
        {
            text = String.valueOf(v.secti());

        }
        else if(e.getActionCommand().equals("-"))
        {
            text = String.valueOf(v.odecti());
        }
        else if(e.getActionCommand().equals("/"))
        {
            text = String.valueOf(v.vydel());
        }
        else if(e.getActionCommand().equals("*"))
        {
            text = String.valueOf(v.vynasob());
        }

        labVysledek.setText(text);
    }

Výjimka

Nyní by program měl fungovat. Co se ale stane, pokud budu dělit nulou nebo nezadám celá čísla? GUI program sice nespadne, ale v terminálu nám chyby samozřejmě vyskočí. Jelikož bychom museli ošetřovat všude vstupy a k tomu ještě dělení nulou, bylo by to pěkných pár podmínek navíc. Mnohem lepším způsobem jsou tzv. Výjimky. Výjimka má dva bloky – try a catch.

try
{
// běh bez chyby
}
catch(Exception ex)
{
// běh s chybou
}

Jednoduše, pokud nenastane chyba, provede se blok try, pokud nastane jakákoliv chyba, nastane blok catch – chyby můžeme ještě dál dělit, ale o tom snad někdy příště. Za catch je parametrem objekt nějaké z výjimkových tříd. My použijeme třídu Exception. Finální kód bude tedy vypadat následovně:

public void actionPerformed(ActionEvent e)
{
    try
    {
        int cislo1 = Integer.parseInt(tfCislo1.getText());
        int cislo2 = Integer.parseInt(tfCislo2.getText());
        String text = "";

        Vypocet v = new Vypocet(cislo1, cislo2);

        if(e.getActionCommand().equals("+"))
        {
            text = String.valueOf(v.secti());

        }
        else if(e.getActionCommand().equals("-"))
        {
            text = String.valueOf(v.odecti());
        }
        else if(e.getActionCommand().equals("/"))
        {
            text = String.valueOf(v.vydel());
        }
        else if(e.getActionCommand().equals("*"))
        {
            text = String.valueOf(v.vynasob());
        }

        labVysledek.setText(text);
    }
    catch(Exception ex)
    {
        labVysledek.setText("Chyba");
    }

}

V příští lekci, Layouty v Java Swing, se zaměříme na 8 základních layoutů ve formulářových aplikacích Java Swing.


 

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 919x (5.98 kB)
Aplikace je včetně zdrojových kódů v jazyce Java

 

Předchozí článek
Java GUI - událost
Všechny články v sekci
Java Swing bez grafického návrháře
Přeskočit článek
(nedoporučujeme)
Layouty v Java Swing
Článek pro vás napsal Samik11
Avatar
Uživatelské hodnocení:
24 hlasů
Autor se věnuje primárně programování v jazyce Java. Nestraní se ani C# nebo PHP.
Aktivity