autor: Ivan Kupka

Verzia 1

home uvod K1 K2 K3 K4 K5 K6 K7 K8 K9 K10 K11 K12 K13 K14

Java 14

 

3GUI. Udalosti. Ďalšie grafické prvky

 

Cieľom kapitoly je ukázať súhru nových grafických prvkov s ich poslucháčmi. Zoznámime sa okrem iného s triedami JMenuItem, JMenu, JMenuBar, JCheckBox, JFileChooser a JOptionPane. Takisto s poslucháčmi, schopnými reagovať na udalosti, týkajúce sa kontajneru, textového poľa, poprípade kláves.

 

Filozofia pridávania prvkov na materskú komponentu a filozofia práce s poslucháčmi-listenermi je nám už známa. Teraz rozšírime zoznam prvkov o tie najčastejšie používané. Ukážeme na jednoduchých príkladoch, ako spolupracujú s poslucháčmi.

 

Ponuky

Nasledujúci kód predstavuje v práci prvky JMenuItem, JMenu, JMenuBar, JtextField. Prvé tri umožňujú pracovať s ponukami.  K riadku ponúk JmenuBar pridávame ponuky typu JMenu a ku každej ponuke ,môžeme pridať položky ponuky typu JMenuItem.  V našom prípade prvú ponuku tvoria mená hrdinov, druhú ponuku mená hrdiniek. Keď zvolíme mená hrdinov, hrdiniek, objaví sa v políčku text. Túto činnosť zaobstarajú poslucháči jednotlivých položiek ponuky. Políčko má tiež svojho poslucháča. Ten pri editovaní políčka začne po stlačení klávesy enter svoju činnosť.

 

Po spustení programu vyberte najprv meno hrdinu. Potom meno hrdinky. Potom stlačte enter. Stlačte enter ešte raz a sledujte pokyny z políčka. Na konci sa presvedčte, že do ponuky „hrdina“ pribudla nová položka. Vyskúšajte jej činnosť. Pozrite sa potom do kódu a zistite, ktorý poslucháč zabezpečuje činnosť novej položky.

 

Kód Gr3.1

 

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

 

public class Ponuky extends JFrame{

 

  JTextField  policko = new JTextField(" Zvol si dvojicu. ",20);

  JMenu menu1 = new JMenu("hrdina");

  JMenu menu2  = new JMenu("hrdinka");

 JMenuItem[] muzi = {new JMenuItem("Tarzan"),new JMenuItem("Conan"),new JMenuItem("Herkules")};

 JMenuItem[] zeny = {new JMenuItem("Snehulienka"),new JMenuItem("Popoluska"),new JMenuItem("Evita")};

 

   Container cp = getContentPane();

 

  private ActionListener uchoMenus1 = new ActionListener() {

    public void actionPerformed(ActionEvent e) {

      policko.setText(((JMenuItem)e.getSource()).getText() + " a ");

    }

  };

 

  private ActionListener uchoMenus2 = new ActionListener() {

     

    public void actionPerformed(ActionEvent e) {

           String text = policko. getText();

        if(text.endsWith(" a")) {

         policko.setText("Zacni pisanie hrdinom.");

          }

         else {

          policko.setText(policko. getText() + " " + ((JMenuItem)e.getSource()).getText() );

          }//EOElse

     }//EOMethod

   };   

         

     private ActionListener uchoPolicka = new ActionListener() {

       // zisti, ci sa enter stlacil prvy raz

       boolean prvyRaz = true;

      

      public void actionPerformed(ActionEvent e) {

          String  text = policko. getText();

          if(prvyRaz == true) {     

          prvyRaz = false;

           policko.setText(text + "? To je ale blbost!");

          }

          else{

             if(text.startsWith("Napis svoje meno a potom stlac enter:")){

               String meno = text.substring(37,text.length());

               policko.setText("Pridal som hrdinu \"" + meno + "\" " );

               JMenuItem novyHrdina = new JMenuItem(meno);

               novyHrdina.addActionListener(uchoMenus1);

                menu1.add( novyHrdina);

               }//EOIf

               else{

                policko.setText("Napis svoje meno a potom stlac enter:"); 

               }//EOInnerElse

         }//EOElse

    }//EOMethod

  };//EOListener     

 

  

        

  public Ponuky(){

            super("Voliace prvky ");

             setSize(500,70);

            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

 

    policko.setFont(new Font("plain",1,14 ));

         policko.addActionListener(uchoPolicka);

       

    // Pridavanie JMenuItems - aj s Listenermi  

    for(int i = 0; i < 3; i++) {

      menu1.add(muzi[i]);

      muzi[i].addActionListener(uchoMenus1);

      menu2.add(zeny[i]); 

      zeny[i].addActionListener(uchoMenus2);

     }//EOFor

  

     //Ukladanie prvkov na kontajner 

     cp.setLayout(new BoxLayout(cp,BoxLayout.X_AXIS));

     // ulozenie menus na JMenuBar

     JMenuBar menus = new JMenuBar();

     menus.add(menu1);

     menus.add(menu2);  

      

     cp.add(Box.createHorizontalGlue());

    // pridanie popisky

     policko.setToolTipText(" policko ");

     cp.add(policko);

          cp.add(Box.createHorizontalStrut(10));

          cp.add(menus);

          cp.add(Box.createHorizontalGlue());      

   }//EndOfTheConstructor

      

   

   public static void main(String[] args){

          Ponuky vb = new Ponuky();

          vb.setVisible(true);

   }//EOMain

         

}//EOClass Ponuky

 

Komentáre:

Ak po spustení programu podržíte kurzor myši nad políčkom, po čase sa objaví popiska s nápisom „policko“. Je to vďaka príkazu

policko.setToolTipText(" policko ");

Metóda setToolText(String s) je definovaná pre mnohé iné grafické prvky, ako napríklad tlačítka,  celkovo pre všetkých potomkov  triedy JComponent.

Riadok

policko.setFont(new Font("plain",1,14 ));

nastavil pre políčko konkrétny font.

 

Zaškrtávacie políčka

 V nasledujúcom kóde sú ukázané dve veci. Za prvé práca so zaškrtávacími políčkami. Za druhé je tu využitá možnosť odobrať (pridať) poslucháča počas behu aplikácie. Viď riadky

prvyCheck.removeActionListener(ucho1);

a

prvyCheck.addActionListener(ucho1);

 

 

Kód Gr3.2

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

 

public class Volme extends JFrame{

         

   Container cp = getContentPane();

 

          JTextField  policko = new JTextField(26);

          JCheckBox prvyCheck = new JCheckBox();

          JCheckBox druhyCheck = new JCheckBox(" odober posluchaca",false);

 

  private Posluchac1 ucho1 = new Posluchac1();

          private Posluchac2 ucho2 = new Posluchac2();

 

               

  class Posluchac1 implements ActionListener {

    public void actionPerformed(ActionEvent e) {

           if(prvyCheck.isSelected())

      policko.setText("Prvy zaskrtnuty");

     else

      policko.setText("Prvy odznaceny");

 

     }

   }

  

   class Posluchac2 implements ActionListener {

     public void actionPerformed(ActionEvent e) {

           if(druhyCheck.isSelected()){

           prvyCheck.removeActionListener(ucho1);

           policko.setText("Druhy zaskrtnuty, ubral posluchaca prvemu");

           druhyCheck.setText("pridaj posluchaca");

           }//EOIf

            else {

              policko.setText("Druhy odznaceny, pridal posluchaca prvemu");

             prvyCheck.addActionListener(ucho1);

                 druhyCheck.setText("odober posluchaca");

                }//EOElse

        }//EOMethod

    }//EOInnerClass

 

  

          public Volme(){

                   

                    super("Voliace prvky ");

                        setSize(500,80);

            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

 

                    prvyCheck.addActionListener(ucho1);

                    druhyCheck.addActionListener(ucho2);

                     

        cp.setLayout(new FlowLayout());

      cp.add(Box.createHorizontalGlue());

      cp.add(policko);

         cp.add(Box.createHorizontalStrut(10));

                  prvyCheck.setToolTipText(" CheckBox ");

            cp.add(prvyCheck);     

                  cp.add(Box.createHorizontalStrut(10));

            druhyCheck.setToolTipText(" CheckBox s textom ");

            cp.add(druhyCheck);   

            cp.add(Box.createHorizontalGlue());      

                

    }//EOConstructor

      

  

     public static void main(String[] args){

          Volme vb = new Volme();

          vb.setVisible(true);

     }//EOMain

         

 

Reagovanie na klávesy. Poslucháči okna textového poľa

Po predchádyajúcich jednoduchších príkladoch sa už  ľahšie zorientujeme v nasledujúcom komplexnejšom. Je to príklad zlúčenia a prepojenia viacerých reakcií na udalosti kláves a na udalosť v textovom poli.

 

K panelu je pridaný poslucháč, ktorý reaguje na stlačenie a uvoľnenie kláves. Príslušný kód klávesy a jej meno sa odosiela do textového poľa, kde sa zobrazí. Ak sa v textovom poli objaví String „Delete“, text po piatich sekundách z poľa zmizne. Text „Delete“ sa v poli objaví, ak napríklad klepneme na klávesu „Delete“, alebo ak ho do textového poľa sami napíšeme.

 

V príklade vidno rozdiel medzi udalosťami „keyPressed“ a „keyTyped“. Prvá nastane po stlačení ľubovoľnej klávesy, druhá len po stlačení „znakovej“, „písmenkovej“ klávesy. Teda takej, ktorá pridá znak na obrazovku, keď píšeme v nejakom editore.

 

Na tri klávesy reaguje program špeciálne: sú to klávesy „r, g, b“. Slúžia na pridávanie červenej (red – r) , zelenej, alebo modrej zložky farby. Všetky tri zložky, reprezentovateľné číslom od 0 do 255, sa zmiešajú do výslednej farby, ktorú vidno na hornej polovici okna. Jednotlivé tlačítka „R, G, B“ slúžia iba na zobrazenie sýtosti červenej (prvé tlačítko), zelenej (druhé tlačítko) a modrej farby (samozrejme, tretie tlačítko).  Nemajú pridelených žiadnych poslucháčov. Stredné tlačítko má k dispozícii popisku. Na tej si možno pozrieť aktuálne nastavenú trojicu čísel RGB. Keď nechceme čísla od 0 do 255 zväčšovať, ale naopak, chceme ich zmenšovať, podržíme klávesu „Ctrl “ a opäť pracujeme s klávesami „r,g,b“ na klávesnici.

 

Poslucháč komponenty v našom príklade robí niečo, čo by seriózna,  konzervatívna aplikácia asi robiť nemala: keď presunieme okno, toto najprv na tri sekundy zmizne. Až potom sa znovu objaví,  už na novom mieste.

 

Kód Gr3.3

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

 

public class Klavesy extends JFrame{

         

          JButton rButton = new JButton(" R ");

          JButton gButton = new JButton(" G ");

          JButton bButton = new JButton(" B ");

         

         

   Container cp = getContentPane();

  Box vodorovny = Box.createHorizontalBox();

  TextArea txt = new TextArea(12,40);

 

  Posluchac uchoKlaves = new Posluchac();

   UchoTextu uchoTextu = new UchoTextu();

   UchoKomponenty uchoKomponenty = new UchoKomponenty();

 

  int red = 0;

  int green =0;

   int blue = 0;

        

         

            public Klavesy(){

                     super(" Pokus s klavesmi ");

                     

                     setSize(500,400);

       setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

 

        // prvi dvaja posluchaci pre komponentu, treti pre textove pole

        addComponentListener(uchoKomponenty);

       addKeyListener(uchoKlaves);     

       txt.addTextListener(uchoTextu);

 

 

    cp.setBackground(new Color(red,green, blue));

    cp.setLayout(new BorderLayout());

       

    // panel s tlacitkami bude na severe

    vodorovny.add(Box.createHorizontalStrut(100));

    vodorovny.add(rButton);

          vodorovny.add(Box.createHorizontalGlue());

              vodorovny.add(gButton);     

              vodorovny.add(Box.createHorizontalGlue());

    vodorovny.add(bButton);

    vodorovny.add(Box.createHorizontalStrut(100));

    cp.add(BorderLayout.NORTH,vodorovny);

  

    //panel s textovym polom bude na juhu               

     JPanel pnText = new JPanel();

     pnText.setBackground(new Color(190,130,200));

     pnText.add(new JScrollPane(txt));

     cp.add(BorderLayout.SOUTH,pnText);

        }//EOConstructor

      

  

     // vnutorna trieda:

    

     class Posluchac implements KeyListener {

           int kod = -1;

           boolean ctrl = false;

    

           public void keyPressed(KeyEvent e){

                     kod = e.getKeyCode();

                     if(kod == 17)

                      { ctrl = true;

                              }

                     // rozdiel medzi keyPressed a keyTyped:

                      // sledujte odozvu klavesy F1 pred odkomentovanim

                      // a po odkomentovani nasledujucich riadkov      

              // txt.append("\n Kod stlacenej klavesy: "

         // + String.valueOf(kod));

 

         }

         

        public void keyTyped(KeyEvent e){

           

            txt.append("\n Kod stlacenej klavesy: "

                               + String.valueOf(kod));

                       prefarbi(kod,ctrl);

          }

         

   

   

       public void keyReleased(KeyEvent e){

          int kod2  = e.getKeyCode();

 

          if(kod2 == 17)

                              { ctrl = false;

                              }

 

               String menoKlavesy = e.getKeyText(kod2);      

               txt.append(" \n Meno klavesy: " + menoKlavesy);

          }

     }//EOInnerClass

 

     // vnutorna trieda:

   class UchoTextu implements TextListener{

    

     // Akonahle sa v textovom poli objavi text "Delete"    

     // o 5 sekund sa vsetok text v poli vymaze:

    

     public void textValueChanged(TextEvent e){

         

          String obsah = txt.getText();

          if (obsah.indexOf("Delete") > -1) {

            txt.append("\n O 5 sekund vycistim textove pole.");

            long t1 = 5000 + System.currentTimeMillis();      

            while(System.currentTimeMillis() < t1) ;

            txt.setText("");

          }//EOIf       

       }

     }

    

  // vnutorna trieda:

    class  UchoKomponenty implements ComponentListener {

         

          public void componentResized(ComponentEvent e){

          }

          public void componentHidden(ComponentEvent e){

          }

          public void componentMoved(ComponentEvent e){

              setVisible(false);

           long t1 = 3000 + System.currentTimeMillis();       

            while(System.currentTimeMillis() < t1) ;

           setVisible(true);

             }

        

      public void componentShown(ComponentEvent e){

          }

    }//EOInnerClass

   

   

    // metoda , urcujuca farbu tlacitok a hlavneho panelu cp

    // reaguje na stlacenie klaves r  g  b , (s  kodmi  82  71  66)

    // a na to, ci drzime / nedrzime tlacitko Ctrl

     private void prefarbi(int kod, boolean ctrl){

       if(kod == 82){

         red = zmen(red,ctrl);

         rButton.setText(String.valueOf(red));

             rButton.setBackground(new Color(red,0,0));      

             cp.setBackground(new Color(red,green, blue));

             }

        

       if(kod == 71){

           green = zmen(green,ctrl);

             gButton.setText(String.valueOf(green));

         gButton.setBackground(new Color(0,green,0));      

        cp.setBackground(new Color(red,green, blue));

                     }

                     

           if(kod == 66){

             blue = zmen(blue,ctrl);

             bButton.setText(String.valueOf(blue));

             bButton.setBackground(new Color(0,0,blue));    

                cp.setBackground(new Color(red,green, blue));

           }

 

             // uved udaj o cislach RGB na popiske gButtonu

             String info = String.valueOf(red) + "  " +

                                         String.valueOf(green) + "  " +

                                     String.valueOf(blue);

             gButton.setToolTipText(info);        }

         

         

          // pomocna metoda pre metodu prefarbi

          // zabezpecuje zmensovanie-zvacsovanie

          // kodovych cisel pre farby RGB

       private int zmen(int farba,boolean zmensit){

         if(zmensit){           

           farba = (farba >10)? (farba-10) : farba;

         }

        else {

         farba = (farba < 245)? (farba+10) : farba;

         }

        

         return farba;

       }//EOMethod

        

    

     public static void main(String[] args){

          Klavesy kl = new Klavesy();

          kl.setVisible(true);

          }//EOMain

    }//EOClass

 

Dialógové okno JFileChooser

  Trieda JFileChooser  poskytuje okno, grafické rozhranie, ktoré nám umožňuje vidieť adresáre a súbory. A taktiež bežným spôsobom sa medzi nimi pohybovať. Dovoľuje aj implementovať vykonanie určitej operácie so zvoleným súborom. Touto operáciou  by mohlo byť napríklad preeditovanie súboru alebo prehranie audiosúboru. Celkovoa všetko, čo Java so súbormi dokáže.

 V našom príklade sa najprv objaví malé okienko. Do políčka zapíšeme slovo a stlačíme tlačítko „hľadaj“. Vtedy sa objaví dialógové okno. Po výbere súboru – stlačení tlačítka „Open“ dialógové okno JFileChooser zmizne. Objaví sa  okno správ, vyvolané statickou metódou

JOptionPane.showMessageDialog(...). Okno buď oznámi, že vo vybranom súbore sa hľadaný String nenachádza, alebo vypíše prvý riadok súboru, v ktorom program hľadaný String našiel.

 

Kód3.4

// program umozni zadat String a vybrat subor

// ukaze prvy riadok, v ktorom sa String nachadza

// alebo poda spravu, ze v subore takyto String nie je

 

import javax.swing.*;

import java.awt.*;

import java.awt.event.*;

import java.io.*;

 

// pomocna trieda , hlada ci sa v subore nachadza zadany String

class Hladaj{

 

  // staticka metoda          

  public static String slovo(String text,File f){

           String riadok = "Vyraz \"" +text +  "\" sa v subore " + f.getName() + " nenachadza";

  try{

    String docasny;

    BufferedReader citaj = new BufferedReader(new FileReader(f));

 

    while( (docasny=citaj.readLine())!=null){

          if(docasny.indexOf(text)>-1) {

             riadok = docasny;

             break;      

          }//EOIf

           }//EOWhile

          }//EOTry

         

  catch(FileNotFoundException e){

    return "Subor sa nenasiel. Asi ste ziaden neoznacili."   ;

  }

  catch(IOException e){

    return "Nastal problem pri citani suboru." ;

  }

          return riadok;

  }//EOMethod

}//EOClass Hladaj

 

 

public class FChooser extends JFrame {

 

          JLabel label= new JLabel("Hladane slovo");

          JTextField policko = new JTextField(20);

          JButton tlacitko = new JButton("Hladaj");

         

          public FChooser(){

            Container cp = getContentPane();

            cp.setLayout(new FlowLayout());

            cp.add(label);

            cp.add(policko);

            cp.add(tlacitko);

           

            // pridany poslucahc definovany ako

            //instancia vnutornej anonymnej triedy:

            tlacitko.addActionListener(new ActionListener() {

                    public void actionPerformed(ActionEvent e){

              String coHladas = policko.getText();

                    hladanie(coHladas);

            }});

           

            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            this.setSize(400,100);

            this.setVisible(true);     

                    }

         

            private void hladanie(String hladane){

           

            System.out.println("Spustam hladanie slova " + hladane);       

            JFileChooser c = new JFileChooser();

             

            /////////////FileChooser  dalsie  metody///////////////////

            /*  c.setApproveButtonText("prehladaj");   // zmeni text tlacitka

             String home = System.getProperty("user.dir");

             File homeDir = new File(home);

              c.setCurrentDirectory(homeDir);  // zmeni vychodiskovy adresar na adresar homeDir  

             //////////////////////////////*/

            

      // Ukazka dialogu "Open":

      int rVal = c.showOpenDialog(FChooser.this);

         // pokus: zakomentujte predosly riadok, odkomentujte nasledujuci

        //int rVal = c.showOpenDialog(tlacitko);

         if(rVal == JFileChooser.APPROVE_OPTION) {

         File zvolenySubor = c.getSelectedFile();

         String riadok = Hladaj.slovo(hladane,zvolenySubor);

         JOptionPane.showMessageDialog(null,riadok," prehladany subor: "  +

          zvolenySubor.getName(), JOptionPane.INFORMATION_MESSAGE);

         }

        if(rVal == JFileChooser.CANCEL_OPTION) {

         // nezvolili sme ziadnu cinnost

         }

        }

       

public static void main(String[] args){

 

  FChooser fch = new FChooser();

 }//EOMain

}//EOClass

 

// cvicenie :doplnte kod  tak, aby vyhladavanie zacalo

// aj pri stisnuti tlacitka enter v textovom policku

 

Pozor na štandardnú chybu

Niekedy sa stane, že dôkladne premyslíme správanie sa poslucháča pre určitú komponentu. Príslušnú triedu – Listener vhodne impementujeme a vytvoríme konkrétnu inštanciu tohto poslucháča. Napriek tomu program nerobí to, čo sme chceli. Zabudli sme urobiť posledný krok procesu: zaregistrovať poslucháča u príslušnej komponenty, u príslušného prvku pomocou jednej z metód „add...Listener(...)“.

 

Cvičenia

Cv3.1

Preštudujte si dokumentáciu triedy Font. V kóde Gr3.1 meňte typ fontu, priradený textovému políčku. Nakoniec font nastavte na italiku.

Cv3.2

Doplňte Kód3.2 tak, aby sa vžy pri ubraní alebo pridaní poslucháča objavilo okno správ, ktoré túto udalosť oznámi. Preštudujte si dokumentáciu triedy JoptionPane a použite postupne viac podôb metódy showMessageDialog(..).

Cv3.3

Vytvorte aplikáciu, ktorá umožní „odpočúvať“ prácu na klávesnici a archivovať ju. Môžete vychádzať z kódu Gr3.3.  Aplikácia najprv oznámi používateľovi, aby určitú dobu stláčal klávesy na klávesnici a potom dal stlačením tlačítka signál na ukončenie procesu. Aplikácia si zapamätá

a)    všetky klávesy, ktoré vyvolali udalosť keyPressed a zapíše ich po poradí do súboru.

b)    potom do toho istého súboru zapíše všetky klávesy, ktoré vyvolali udalosť keyTyped.

Potom oznámi používateľovi, kde má daný súbor hľadať.

Cv3.4

Vytvorte malý „SearchBot“, prehľadávací program. Umožní vám najprv zvoliť výraz, ktorý hľadáte a adresár, v ktorom budete hľadať. Po potvrdení voľby prehľadá všetky súbory v danom adresári, ktoré majú príponu txt. Zobrazí zoznam tých, v ktorých sa zvolený výraz-String nachádza. Zároveň umožní vybrať  ľubovoľný z týchto dokumentov a zobraziť jeho obsah v osobitnom okne.

 

Riešenia

Cv3.1.

Napríklad príkazom

policko.setFont(new Font("italika",Font.ITALIC,14 ));

 

© Ivan Kupka

home uvod K1 K2 K3 K4 K5 K6 K7 K8 K9 K10 K11 K12 K13 K14

Vaše komentáre: kupka@fmph.uniba.sk