Uživatelská rozhraní Uživatelská rozhraní 6. cvičení
Úvod do Swing GUI toolkit AWT Abstract Window Toolkit (import java.awt.*) Od počátku Javy, základní stavební kameny pro vytváření komplexních UI. Intenzivní využívání návrhových vzorů (vychází z Model-View-Controler). Swing (import javax.swing.*) Od Javy 2, rozšiřuje a staví na AWT, obsahuje spoustu nových komponent, standardní dialogová okna, Look & Feel, Také využívání návrhových vzorů (vychází z Model-View-Controler). Vzhled i chování prvků je implementováno v Javě. Management rozložení komponent – 8 typů základních layoutů, ale existuje mnoho dalších. Součást JFC (Java Foundation Classes). Podpora pro datové přenosy (Cut/Copy/Paste, Drag & Drop). Obsahuje Undo Framework (podpora Undo a Redo operací). Internacionalizace, Accesibility (zpřístupnění obsahu zrakově postiženým). Rovněž multiplatformní, alternativou je např. SWT od IBM.
Prerekvizity Java SE Development Kit (JDK) Manuály Specifikace API: Tutoriály: Editory NetBeans, Eclipse, PSPad, …
Základní informace o GUI v Javě Každá komponenta viditelná na obrazovce musí být potomkem java.awt.Component Jména vizuální komponenty z balíku java.swing začínají písmenkem J (JComponent, JFrame, JFileChooser, …) Dodržuje se zde téměř všude návrhový vzor MVC, takže i tlačítko má svůj model java.swing.ButtonModel Existuje technologie JavaBean, která je určeny především (ale ne jenom) pro vytváření grafických komponent.
Ukázky možností swing GUI \demo\jfc\SwingSet2\ (online verze – Java WebStart)
Nejpoužívanější komponenty JFrame (zbylé dvě jsou JDialog a JApplet) Okno aplikace, obsahuje standardní prvky (lze je vypnout), komunikuje s OS. Kontejnerem pro další komponenty (např. JButton, JLabel, JPanel) není přímo JFrame, ale automaticky vytvořený ContentPane (getContentPane()). Title bar Min, max, zavřít ContentPane
Další komponenty Kontejnery: JPanel, JTabbedPane, JSplitPane, JScrollPane, … Usnadňují umísťování dalších komponent. Atomické komponenty: JLabel, JButton, JComboBox, JTextField, JTable,… Umožňují interakci s uživatelem a zobrazují informace.
Postup při použití obecné komponenty 1. Instanciace. JButton btn = new JButton(“tlačítko“); 2. Konfigurace. //většinou není třeba btn.setPrefferedSize(new Dimension(100, 20)); btn.setSetText(“TLAČÍTKO”); 3. Jedná-li se o kontejner, vložení potomků. 4. Nejedná-li se o JFrame, vložení komponenty do kontejneru (např. JContentPane, JPanel). panel.add(btn); 5. Registrace posluchačů. btn.addXXXListener(listener);
Zdroj událostí – Objekt, který generuje události – Spravuje seznam registrovaných posluchačů Posluchač (listener) – Objekt, který chce být o události informován – Musí být registrován u zdroje událostí – Musí implementovat dohodnuté rozhraní Události (1)
Události (2) Zdroj událostí Registrovaní posluchači Posluchač addEventListener registrace Informace o události EventObject e vznik události nastala událost (e)
Posluchač se zaregistruje u zdroje událostí (např. u tlačítka, na jehož stisknutí čeká) Uživatel stiskne tlačítko – vznikne událost Zdroj události (tlačítko) projde seznam registrovaných posluchačů a každému z nich oznámí vznik události: – Zavolá dohodnutou metodu rozhraní posluchače – Metodě předá informace o události (podtřída java.util.EventObject) Zpracování událostí
Události: Model Event – Listener Zpracování událostí Source MyListener addFooListener AddFooListener fireSomethingHappend somethingHappend FooEvent
Objekt události – musí dědit z java.util.EventObject – Má se jmenovat Event – Musí mít konstruktor s alespoň jedním parametrem (zdroje událostí) Rozhraní posluchače (ListenerType) – Musí dědit z java.util.EventListener – Má se jmenovat Listener – Jednotlivé metody by mněli mít jeden parametr (událost) – Mají vracet void Zdroj událostí(JavaBean) musí mít metody public void add ( listener) throws java.util.TooManyListenersException; public void remove ( listener) Události - Shrnutí
GUI události Balík java.awt.event a java.swing.event Každá komponenta podporuje notifikaci následující posluchačů a mnoha dalších – addComponentListener, addMouseListener addMouseMotionListener, addKeyListener Adaptéry slouží k tomu aby nebylo třeba implementovat všechny metody, když potřebujeme obsloužit jen jednu. – Adaptéry implementují všechny metody jako prázdné. – KeyAdapter, MouseAdapter, MouseMotionAdapter
Ukázka použití Adaptéru txtOut = new JTextField(); txtOut.addMouseListener(new java.awt.event.MouseAdapter() public void mouseClicked(java.awt.event.MouseEvent e) { //udělej něco } }); Bez použití adaptéru txtOut.addMouseListener(new java.awt.event.MouseListener() { public void mouseClicked(java.awt.event.MouseEvent e) { //udělej něco public void mouseEntered(MouseEvent paramMouseEvent) { public void mouseExited(MouseEvent paramMouseEvent) { public void mousePressed(MouseEvent paramMouseEvent) { public void mouseReleased(MouseEvent paramMouseEvent) { } });
Layout Management LM ovládají rozmístění komponent v rámci kontejneru. Příkaz pack() nastaví velikost okna tak aby komponenty obsažené v něm mněli pokud možno preferovanou velikost. BoxLayoutFlowLayoutGridLayout BorderLayoutGridBagLayout“Null” Layout
Layout Management Rozhraní java.awt.LayoutManager a java.awt.LayoutManager2, který je rozšířením prvního. Každý si může vytvořit svůj vlastní layout manager stačí implementovat jedno z těchto dvou rozhraní. Přehled všech tříd které implementují dané rozhraní najdete na:
FlowLayout Nejjednodušší layout, vkládá komponenty na řádek zleva doprava dokud je na řádku místo, pak pokračuje dalším řádkem. Každý řádek je vycentrovaný. Řídí se tzv. preferred size atributem komponenty. Je to výchozí rozložení pro JPanel.
BorderLayout Rozděluje kontejner do pěti regionů. Výchozí centrální region je maximalizovaný, ostatní zabírají pouze minimální potřebnou plochu. Každý region může obsahovat maximálně jednu komponentu. Je to výchozí rozložení pro ContentPane (JFrame). Pozor pokud to jde je volné místo přiděleno komponentně ve středu takže, pokud boční komponenty nemají minimální velikost (např. prázdný frame) nebudou vidět. Konstanty: CENTER, WEST, EAST, SOUTH, NORTH Pokud použijete BorderLayout v kontejneru CntentPane okna a necháte „okraje“ volné můžete vytvořit toolbar java.swing.JToolBar, který bude moct přesouvat myší na libovolnou stranu okna, bez nutnosti psaní nějakého speciálního kódu.
BoxLayout Řadí komponenty za sebe do řádku (LINE_AXIS) nebo podsebe do sloupce (PAGE_AXIS). Obdoba FlowLayout, ale s více možnostmi.
GridLayout Umísťuje komponenty do buněk mřížky. Každá komponenta využije celý prostor buňky. Všechny buňky mají stejnou velikost.
GridBagLayout Jeden z nejkomplexnějších layoutů. Umísťuje komponenty do buněk mřížky obdobně jako GridLayout. Řádky i sloupce mohou mít různou velikost. Komponenta může zabírat více buněk (rowspan, columnspan).
Implicitní správce rozvržení Při vytvoření jakéhokoliv potomka třídy Container má automaticky předdefinován i správce rozvržení. JPanel FlowLayout JFrameBorderLayout JDialogBorderLayout JAppletBorderLayout BoxBoxLayout
Specifikace API Důležitou součástí programování bude vyhledání informací o třídách, metodách, konstruktorech, zděděných vlastnostech apod. Proto se snažte spřátelit na cvičení i s API specifikací ( ). Příklad na vlastnosti JButton
Specifikace API Každý popis třídy nebo rozhraní obsahuje všechny důležité informace o dané třídě rozhraní: Ve kterém balíku je třída obsažena Ze kterých tříd dědí Seznam rozhraní, která implementuje Podtřídy Popis Seznam třídních proměnných, konstruktorů, metod Podrobné popisy předchozích (argumenty, vyjímky)
Praktická úloha Pro cvičení použijeme šablonu, na které se budeme dále seznamovat s komponentami zahrnutými ve Swing API. Design si můžete upravit libovolně podle sebe. Pokuste se vyzkoušet základní prvky, včetně nastavení jejich vlastností.
Praktická úloha
Použití třídy JFrame public class TempConv extends JFrame implements ActionListener { JTextField txtIn; … } Ovládací prvky, se kterými budeme pracovat (číst jejich stav), deklarujeme zde jako atributy třídy TempConv. Základní třída okna aplikace. Slouží k registraci posluchačů, viz. dále.
Základní operace v konstruktoru public TempConv() { super(“Převod teplot”); //setMinimumSize(new Dimension(420, 300)); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); Container content = getContentPane(); … } Získáme kontejner pro ovládací prvky. Nastavení titulku přes konstruktor třídy JFrame. Bez tohoto řádku by nedošlo po zavření okna k ukončení aplikace.
Zpracování událostí – varianta 1 public class TempConv extends JFrame implements ActionListener { … JButton btn = new JButton(“Převod”); btn.addActionListener(this); … public void actionPerformed(ActionEvent evt) { // provedení konverze hodnot … } … } Registrace posluchače událostí vyvolaných tlačítkem. Reakce na událost.
Zpracování událostí – varianta 2 JButton btn = new JButton(“Převod”); btn.addActionListener(new ActionListener() public void actionPerformed(ActionEvent evt) { // provedení konverze hodnot … }); Registrace posluchače událostí vyvolaných tlačítkem. Reakce na událost. Oproti předchozí variantě není problém obsloužit více jak jedno tlačítko v okně. Doporučovaná metoda obsluhy událostí!
Obrázek protected JComponent getImage(){ // cast pro obrazek JPanel panel = new JPanel(); ImageIcon i= new ImageIcon("d:/URO/cv/thermo2.png"); // ImageIcon(this.getClass().getResource("thermo2.png")); // pro nacitani obrazku napr. uvnitr JAR souboru JLabel l=new JLabel(i); panel.add(l); return panel; }
RadioButton JRadioButton Doporučuji použít společně se třídou javax.swing.ButtonGroup, která zajistí vytvoření skupiny tlačítek, kde může být vybránu pouze jedno tlačítko. ponents/button.html
Borders Najdete je v balíku javax.swing.border Zajímavostí je vytvoření rámečku s textem, který se tvoří tak že se vytvoří objekt třídy TitledBorder, ten však vykresluje pouze text a musí v sobě obsahovat ještě další rámeček, který se postará o vytvoření samotného rámu kolem komponenty. BorderFactory.createTitledBorder( BorderFactory.createEtchedBorder(EtchedBorder.RAIS ED), "Směr převodu„,…) ); Lze vytvořit rámeček s více jak jedním textem?
Dopracovat výpočet a vzhled. Děkuji za pozornost.