Kapitola 1. Přehled užitečných komponen

Obsah

1.1. Co bude dnes
1.2. JCheckBox a JRadioButton
1.3. JMenu
1.4. JScrollPane
1.5. JList
1.6. JComboBox
1.7. JSpinner
1.8. JDialog
1.9. JFileChooser
1.10. JEditorPane a JTextPane
1.11. JInternalFrame
1.12. JTable a JTree
1.13. O generickém programování v Javě

1.1. Co bude dnes

  • přehled nejčastěji používaných komponent

  • cílem je sdělení: toto jsou jména těch nejdůležitějších komponent a toto jsou jejich důležité metody a nastavení

  • komponenty vždy umí mnohem víc než ukáži na přednášce => a proto tato prednáška bude obsahovat rekordní počet odkazů na Swing tutorial

  • odkaz nejdůležitělší -- galerie: http://v1.dione.zcu.cz/java/docs/tutorial/ui/features/components.html

1.2. JCheckBox a JRadioButton

  • obě třídy jsou potomkem javax.swing.AbstractButton a javax.swing.JToggleButton a obě implementují přepínač - tj. tlačítko, které se po kliknutí nevrací zpět do polohy před kliknutím

    • pro zjištění stavu použijete metodu isSelected() zděděnou z AbstractButton

  • na JCheckBox nejsou kladeny zadné další podmínky

  • instance JRadioButton bývají používány spolu s instancí třídy ButtonGroup, která slouží jako kontejner pro několik JRadioButton ... ButtonGroup zaručuje, že pouze jedna instance JRadioButton je aktivni (její isSelected() vrací true)

    JRadioButton firstradiobutton = new JRadioButton("One");
    JRadioButton secondradiobutton = new JRadioButton("Two");
    
    ButtonGroup buttongroup = new ButtonGroup();
    
    buttongroup.add(firstradiobutton);
    buttongroup.add(secondradiobutton);

1.3. JMenu

  • použití JMenu jsme viděli na poslední prednášce

  • menu nabízí uživateli výběr z několik možností a je velmi úsporné co do prostoru, který zabere

  • použití Action třídy pokud akce "schovaná" za JMenuItem je duplikovaná někde jinde v GUI (jiný JMenuItem nebo v tool bar), jak jsme již viděli

  • Jako položku menu lze umístit i JRadioButtonMenuItem, JCheckBoxMenuItem a JMenu (coby submenu)

  • http://java.sun.com/docs/books/tutorial/uiswing/components/menu.html

1.4. JScrollPane

  • víme co to je scroll bar (hezki česki posuvňýk), který je implementován třídou JScrollBar -- ta se však zřídka používá přímo

  • žádna Swing componenta nemá scroll bar "sama od sebe" ale ...

  • ... JScrollPane je panel který má navíc scroll bar ... a to vertikální, horizontální nebo oba dva

  • konstruktor JScrollPane(int, int) -- parametry jsou scroll bar policies tedy pravidla

    • ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED (default)

    • ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS

    • ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER

    • ... stejné pro horizontální scroll bar

  • http://java.sun.com/docs/books/tutorial/uiswing/components/scrollpane.html (pozor: tenhle tutorial s obrázkem jednoho dokáže zahltit -- příklad s obrázkem je totiž o dost složitější než by musel býr pro demostraci základního použití)

  • jednodušší (ale zcela bežné) použití uvidíme v části o JList

1.5. JList

  • komponenta na výběr jednoho nebo více prvků

  • základní použití je umístit JList na JScrollPane, aby vždy bylo možné vidět všechny položky

  • kolik položek najednou lze vybrat uržuje tzv. list selection model

    • SINGLE_SELECTION

    • SINGLE_INTERVAL_SELECTION

    • MULTIPLE_INTERVAL_SELECTION (default)

  • Příklad JList na JScrollPane s defaultním list selection modelem:

String[] data = {"one", "two", "three", "four", "five"}; // tzv. "model"
list = new JList(data); // data jsou typu Object[], model je pole
list.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
list.setLayoutOrientation(JList.VERTICAL);
list.setVisibleRowCount(-1);
...
JScrollPane listScroller = new JScrollPane(list); // scrollbar na 1 radek
listScroller.setPreferredSize(new Dimension(250, 80));
  • obsluha události ListSelectionEvent v ListSelectionListener#valueChanged()

    • chybou je vést si vlastní záznamy o tom které položky jsou vybrány -- "opravdoví programátoři" mívají pocit že by si to měli hlídat sami, ale tento pocit je mylný

    • zjištění, které položky jsou vybrány se správně dělá takto:

      • int getSelectedIndex()

      • int[] getSelectedIndices()

  • JList umí používat model, což je objekt, který implementuje ListModel rozhraní

    • default je DefaultListModel, který na obyčejné věci stačí

    • pokud DefaultListModel nestačí, je třeba odědit od AbstractListModel nebo implementovat ListModel -- více o modelech na přístí přednášce o JTable

  • položky vykresluje ListCellRenderer

1.6. JComboBox

  • platí více-méně to samé jako pro JList

  • narodíl od JList pro JComboBox má smysl mít vybránu právě jednu položku

1.7. JSpinner

  • použijete, namísto JComboBox když

    • je příliš mnoho možných hodnot a

    • je zřejmé jaké hodnoty to jsou

  • umí vracet nejen String, ale také int nebo datum

    //Add second label-spinner pair.
    int currentYear = calendar.get(Calendar.YEAR);
    SpinnerModel yearModel = new SpinnerNumberModel(currentYear, //initial value
                                                    currentYear - 100, //min
                                                    currentYear + 100, //max
                                                    1);                //step
  • umí pracovat s modelem (pořád platí, že o tom, co to je model, si povíme až příště)

    • nejjednodušší model je pole (podobně jako u JList)

    • SpinnerListModel, SpinnerNumberModel, and SpinnerDateModel

  • http://java.sun.com/docs/books/tutorial/uiswing/components/spinner.html

1.8. JDialog

  • Dialog je nezávislé okno navržené pro jednoduchou a krátkou interakci s uživatelem či krátké zprávy jako např. chybové hlášky nebo varování.

  • Swing nabízí několik standardních dialogů

    • statické metody třídy JOptionPane (viz níže)

    • ProgressMonitor může zobrazit dialog s "progress bar"

    • JColorChooser a JFileChooser

      • metoda třídy JFileChooser setMultiSelectionEnabled(boolean b) ... default je false

    • Printing API nabízí dialog pro tisk

  • dialogy vytvářené JOptionPane jsou defaultně modální okna, pro nemodální je třeba odědit přímo od JDialog

    • setModal(boolean modal)

  • always-on-top ... tomu se raději vyhněte

    • setAlwaysOnTop(boolean alwaysOnTop)

1.9. JFileChooser

final JFileChooser fc = new JFileChooser();
...
//fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
//fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);

int returnVal = fc.showOpenDialog(parentComponentOfTheDialog);
// alternativně: int returnVal = fc.showDialog(parentComponentOfTheDialog, "Open");

if (returnVal == JFileChooser.APPROVE_OPTION) { 
   File file = fc.getSelectedFile();
   // tady lze pracovat s obejktem třídy File -- napříkad jej otevřít a číst
   log.append("Opening: " + file.getName() + "." + newline);
} else {
   log.append("Open command cancelled by user." + newline);
}
  • selection mode JFileChooser.DIRECTORIES_ONLY nebo JFileChooser.FILES_AND_DIRECTORIES viz výše

  • filtrování podle přípony .. je nutno naimplementovat metodu accept(File f) třídy FileFilter

    • typicky odědíte svojí třídu (např. ImageFilter) od třídy FileFilter a přetížíte metodu accept

       public boolean accept(File f) {
          if (f.isDirectory()) {
              return true;
          }
          String extension = Utils.getExtension(f);
          if (extension != null) {
              if (extension.equals("gif") || extension.equals("png")) {
                  return true;
              } else {
                  return false;
              }
          }
          return false;
      }
      
    • http://java.sun.com/docs/books/tutorial/uiswing/components/filechooser.html#filters

     //Add a custom file filter and disable the default (Accept All) file filter.
     fc.addChoosableFileFilter(new ImageFilter());
     fc.setAcceptAllFileFilterUsed(false);
  • metoda void setMultiSelectionEnabled(boolean b) ... default je false

  • v tříde JFileChooser používáme tři metody na zobrazení dialogu:

    • showOpenDialog

    • showSaveDialog

    • showDialog ... zde nápis na tlačítku je parametrem metody

1.10. JEditorPane a JTextPane

1.11. JInternalFrame

1.12. JTable a JTree

  • JTable příště (a počítejte, že přístě pravděpodobně hodně přetáhneme), JTree přespříště

1.13. O generickém programování v Javě

  • způsob programování, které co nejvíce odděluje algoritmy a datové typy

    • umožňuje zápis algoritmu s minimílní vazbou na konkrétní datový typ použitím tzv. šablon (templates)

  • v Javě poznáte použití genericty podle použití znaků <> ... uvnitř je typicky buď otazník nebo nějaký identifikátor začínající velkém písmenem

  • obecně je dobrý zdroj základních informací pro rychlou orientaci v problematici (a nakonec i v cizím kódu) http://en.wikipedia.org/wiki/Generics_in_Java

  • motivace -- zefektivňují práci

    • příklad c Collection tutoriálu -- je vidět základní použití

      • nejprve "klasicky" -- bez genericity

        // Removes 4-letter words from c. Elements must be strings
        static void expurgate(Collection c) {
            for (Iterator i = c.iterator(); i.hasNext(); )
              if (((String) i.next()).length() == 4)
                i.remove();
        
      • nyní s generictou

        // Removes the 4-letter words from c
        static void expurgate(Collection<String> c) {
            for (Iterator<String> i = c.iterator(); i.hasNext(); )
              if (i.next().length() == 4)
                i.remove();
        }
        
    • příklad z Wikipedie, kde je vidět včasné odhalení programátorské chyby

      • nejprve "klasicky" -- bez genericity

          List v = new ArrayList();
          v.add("test");
          Integer i = (Integer)v.get(0);        // Run time error
      • nyní s generictou

          List<String> v = new ArrayList<String>();
          v.add("test");
          Integer i = v.get(0); // (type error)  Compile time error
    • nejčastěji se s generictou setkáte při použití kolekcí

      • ukázka části definic roozhraní List a Iterator z balíčku java.util

          public interface List<E> { 
            void add(E x);
            Iterator<E> iterator();
          }
          public interface Iterator<E> { 
            E next();
            boolean hasNext();
          }
      • použití:

        List<Integer> ints = new ArrayList<Integer>();
        ints.add(42);
        ints.add(256);
        
    • List<?> znamená, že můžete použít jakýkoliv objekt

    • List<? extends Number> znamená, že můžete použít jakýkoliv potomek Java třídy Number

    • často si lidé mylně myslí, že kduře je třída Integer potomkem třídy Number, tak i List<Integer> je potomkem List<Number>