Programowanie w języku JAVA Wykład IV Swing - GUI
Architektura 2 JFC (Java Foundation Classes) zbiór klas do budowy interfejsu graficznego użytkownika i interaktywności aplikacji Javy Komponenty Swing etykiety, przyciski,listy, panele, okna, itd., Przełączany wygląd Look-and-Feel dostosowanie GUI do platformy systemowej, wiele różnych wyglądów, API Dostępności (Accessibility API) przesyłanie informacji z GUI do urządzeń typu ekrany Braila, Java 2D biblioteka do tworzenia wysokiej jakości grafiki 2D, Internacjonalizacja aplikacje mogą wykorzystywać różne języki i zlokalizowane dane
Architektura Architektura oparta o zorientowaną obiektowo dekompozycję projektową interfejsu użytkownika MVC (Model-view-controller) 3
Architektura 4 Model opisuje stan komponentu, np. czy przycisk jest wciśnięty, jaki jest tekst w polu tekstowym. Może być odpowiedzialny za pośrednią komunikację pomiędzy kontrolerem i widokiem. Nie zna referencji do widoku i kontrolera. Wysyła zdarzenia, rozgłasza. Linie -- Widok określa wizualną reprezentację modelu komponentu. Wyświetla odpowiedni kolor, czcionkę, itd. Odpowiada za aktualizację widoku. Odbiera bezpośrednie komunikaty od kontrolera i pośrednie od modelu. Kontroler jest odpowiedzialny za reakcje komponentu na oddziaływanie za pomocą urządzeń wejściowych: klawiatury i myszy. Jest czuciem komponentu. Decyduje o akcjach jakie są podejmowane kiedy komponent jest używany. Może odbierać bezpośrednie komunikaty od widoku i pośrednie od modelu.
Architektura c.d. Zalety MVC Tworzenie własnego widoku (look and feel) bez modyfikacji modelu Możliwość stworzenia własnego modelu, np: książki telefonicznej o określonej strukturze Możliwość podłączania jednego modelu do wielu różnych widoków Kontenery JApplet, JFrame, JDesktopPane, itd. nie posiadają modelu Niektóre komponenty posiadają więcej modeli: JList (składniki listy i składniki zaznaczenia) 5
Architektura - model-delegat Widok i kontroler tworzą delegata interfejsu graficznego: architektura model-delegat Każdy delegat jest dziedziczony po klasie ComponentUI W celu wymuszenia użycia określonego delegata wykorzystuje się metodę setui() komponentu, np: JButton b = new Button( OK ); b.setui(javax.swing.plaf.metal.metalbuttonui. createui(b)); Zmiana wyglądu całego interfejsu UIManager.setLookAndFeel( "com.sun.java.swing.p laf.motif.motiflookandfeel"); Więcej: http://java.sun.com/products/jfc/tsc/articles/architecture/ 6
Kontenery najwyższego poziomu Wszystkie komponenty Swing muszą być częścią drzewa, którego korzeniem jest kontener: JFrame, JDialog lub JApplet, Budowa okna Frame Do panelu zawartości dodajemy komponenty: okno.getcontentpane().add(przycisk, BorderLayout.NORTH); 7 Możemy dodać cały panel: JPanel cp = new JPanel(new GridLayout(3,3)); cp.add(...); okno.setcontentpane(cp); Dodanie menu: okno.setjmenubar(menu);
Kontenery najwyższego poziomu Wszystkie kontenery najwyższego poziomu posiadają pośredni kontener zwany Root Pane: Glass Pane przykrywa okno jak szyba Layered Pane może zawierać komponenty w porządku względem osi Z 8
Klasa JComponent Wszystkie komponenty Swing których nazwy zaczynają się od J są pochodnymi klasy JComponent Właściwości: settooltiptext() - ustawienie dymku podpowiedzi, setborder() - ustawienie obramowania, paintcomponent() - rysowanie na komponencie, Każdy komponent ma odpowiadający obiekt ComponentUI, który przeprowadza rysowanie, przechwytywanie zdarzeń, ustalanie rozmiaru, itd. jest on zależny od bieżącego wyglądu interfejsu, który ustawiamy poleceniem UIManager.setLookAndFeel(...) putclientproperty() - można dołączyć pary klucz wartość do każdego komponentu (get...) 9
Klasa JComponent II Właściwości c.d.: Umożliwiają ustawianie układu (layout) klasa Component wprowadza metody getprefferedsize, getaligmentx, getminimumsize, getmaximumsize, set... (implementacja w klasach pochodnych) Wspomagają dostępność (accessibility) JComponent udostępnia API dla urządzeń takich jak syntezatory mowy odczytujące interfejs użytkownika, Wspomagają technikę przeciągnij i upuść, Wspomagają podwójne buforowanie płynne rysowanie na ekranie, Umożliwiają definicje skrótów klawiszowych 10 komponent.getinputmap().put(keystroke.getkeystroke( F2 ), pressed ); komponent.getactionmap().put( pressed, akcja(typu javax.swing.action))
Narzędzia do tworzenia GUI Komponenty GUI: np. przyciski, menu, paski przewijania Kontenery (pojemniki): np. aplety, ramki Zdarzenia, pozwalające na zarządzanie systemem i elementami GUI Metody obsługi systemu operacyjnego 11
Tworzenie GUI Dodawanie komponentu do kontenera utworzenie komponentu (obiektu pewnej klasy) określenie kontenera pośredniego panelu z zawartością (ang. content pane) wywołanie metody add() kontenera add(komponent) Kontener także rodzaj komponentu 12
Aplet Przycisk import javax.swing.*; import java.awt.*; public class Przycisk extends JApplet { public void init() { JButton p = new JButton("Naciśnij"); Container kont = getcontentpane(); kont.add(p); } } 13
Rozmieszczenie komponentów Sposób rozmieszczenia komponentów - zależny od zarządcy rozkładu Zastosowanie zarządcy rozkładu metoda setlayout() kontenera 14
Rozmieszczenie komponentów Predefiniowane rozkłady ciągły FlowLayout siatkowy - GridLayout brzegowy BorderLayout kartowy CardLayout torebkowy - GridBagLayout pudełkowy BoxLayout Wiosenny - SpringLayout 15
Rozkład ciągły (FlowLayout) Rozmieszcza komponenty w kolejnych wierszach od lewej do prawej (rozmiar komponentu minimalny) Konstruktory FlowLayout() // wyrównanie do środka FlowLayout(int wyrównanie) FlowLayout(int wyrównanie, int dx, int dy) 16
Rozkład ciągły (FlowLayout) Określenie wyrównania: FlowLayout.LEFT FlowLayout.RIGHT FlowLayout.CENTER Odstęp między komponentami w poziomie (dx) i pionie (dy) domyślnie 5 pikseli 17
Rozkład ciągły aplet PrzyciskFL import javax.swing.*; import java.awt.*; public class PrzyciskFL extends JApplet { public void init() { Container kont = getcontentpane(); kont.setlayout(new FlowLayout(FlowLayout.LEFT)); for(int i=1;i<6;i++) kont.add(new JButton("Przycisk " + i)); } } 18
Rozkład ciągły aplet PrzyciskFL 19
Rozkład siatkowy (GridLayout) Podział kontenera na wiersze i kolumny rozmieszcza komponenty od lewej do prawej i od góry do dołu (rozmiar komponentów aby wypełnić obszar) Konstruktory GridLayout(int wiersze, int kolumny) GridLayout(int wiersze, int kolumny, int dx, int dy) 20
Rozkład siatkowy (GridLayout) Przykład kont.setlayout(new GridLayout(3,2)); 21
Rozkład brzegowy (BorderLayout) Domyślny zarządca rozkładu apletów Dzielenie kontenera na: 4 rejony brzegowe (tyle miejsca, ile to konieczne) rejon środkowy (reszta) Konstruktory BorderLayout() BorderLayout(int dx, int dy) Na slajdach Kopniaka tego slajdu nie ma, moim zdaniem przez pomyłkę to usunął 22
Rozkład brzegowy (BorderLayout) Dodawanie komponentu add(int stała, komponent); Dopuszczalne wartości stałej BorderLayout.NORTH BorderLayout.SOUTH BorderLayout.EAST BorderLayout.WEST BorderLayout.CENTER 23
Rozkład brzegowy aplet PrzyciskBL import javax.swing.*; import java.awt.*; public class PrzyciskBL extends JApplet { public void init() { Container k = getcontentpane(); k.add(borderlayout.north, new JButton("PN")); k.add(borderlayout.south, new JButton("PD")); k.add(borderlayout.west, new JButton("Z")); k.add(borderlayout.east, new JButton("W")); k.add(borderlayout.center, new JButton("C")); } } 24
Rozkład brzegowy aplet PrzyciskBL 25
Rozkład kartowy (CardLayout) JPanel zakladka1 = new JPanel(); JPanel zakladka2 = new JPanel();.. JPanel zakladki = new JPanel(new CardLayout()); zakladki.add(zakladka1, JPanel with Buttons ); zakladki.add(zakladka2, JPanel with JtextField ); źródło:http://java.sun.com/docs/books/tutorial/uiswing/layout
Rozkład torebkowy (GridBagLayout) JPanel pane = new JPanel(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); button = new JButton("Button 1"); c.weightx = 0.5; c.gridx = 0; c.gridy = 0; pane.add(button, c);... button = new JButton("Long-Named Button 4"); c.ipady = 40; //make this component tall c.weightx = 0.0; c.gridwidth = 3; c.gridx = 0; c.gridy = 1; pane.add(button, c); źródło:http://java.sun.com/docs/books/tutorial/uiswing/layout
Constraints Rozkład torebkowy (GridBagLayout) gridx, gridy która komórka gridwidth, gridheight ile komórek w poziomie i pionie fill (HORIZONTAL, VERTICAL, BOTH) jak rozciągać komponent ipadx, ipady rozszerzenie komponentu w stosunku do wymiaru minimalnego insets odległości między komponentami w pionie i poziomie anchor (PAGE_START, PAGE_END, LINE_START, LINE_END, FIRST_LINE_START, FIRST_LINE_END, LAST_LINE_END, and LAST_LINE_START)- położenie w komórce weightx, weighty szerokości procentowe kolumn i wierszy
Rozkład pudełkowy (BoxLayout) JPanel listpane = new JPanel(); listpane.setlayout(new BoxLayout(listPane, BoxLayout.PAGE_AXIS)); JLabel label = new Jlabel(labelText); źródło:http://java.sun.com/docs/books/tutorial/uiswing/layout
Rozkład wiosenny (SpringLayout) Container contentpane = frame.getcontentpane(); SpringLayout layout = new SpringLayout(); contentpane.setlayout(layout); layout.putconstraint(springlayout.west, label, 5,SpringLayout.WEST, contentpane); layout.putconstraint(springlayout.west, textfield, 5,SpringLayout.EAST, label); źródło:http://java.sun.com/docs/books/tutorial/uiswing/layout
Specjalny obiekt ikona Ikona - mały obiekt graficzny (zwykle GIF) Wczytanie ikony z pliku stworzenie obiektu klasy ImageIcon Przykład ImageIcon rys = new ImageIcon("open.gif"); JButton p = new JButton(rys); Container kont = getcontentpane(); kont.setlayout(new FlowLayout(FlowLayout.CENTER)); kont.add(p1); 31
Etykieta (JLabel) Komponent wyświetlający łańcuch znaków lub ikonę (bez możliwości edycji) Konstruktory JLabel() JLabel(String napis) JLabel(String napis, int wyrównanie) JLabel(Icon obrazek) JLabel(Icon obrazek, int wyrównanie) JLabel(String napis, Icon obrazek, int wyrównanie) 32
Etykieta (JLabel) Sposoby wyrównania etykiet np. Label.LEFT Label.RIGHT Label.CENTER 33
Aplet Etykiety (cz. 1) import javax.swing.*; import java.awt.*; public class Etykiety extends JApplet { public void init() { JLabel e1, e2, e3; ImageIcon left = new ImageIcon("left.gif"); ImageIcon right = new ImageIcon("right.gif"); Container k = getcontentpane(); k.setlayout(new GridLayout(3,1)); 34
Aplet Etykiety (cz. 2) } } e1 = new JLabel( Lewy", left, JLabel.LEFT); e2 = new JLabel("Prawy", right, JLabel.RIGHT); e3 = new JLabel("Środek", JLabel.CENTER); k.add(e1); k.add(e2); k.add(e3); Lewy 35
Przycisk (JButton) Komponent, którego naciśnięcie może spowodować wykonanie pewnych czynności Niektóre konstruktory JButton() JButton(String napis) JButton(Icon obrazek) JButton(String napis, Icon obrazek) 36
Inne przyciski JRadioButton przycisk radiowy (grupa przycisków z których tylko jeden może być wciśnięty) JRadioButton b1 = new JRadioButton( Opcja 1 ); b1.setactioncommand(nazwa przycisku 1); b1.setselected(true); JRadioButton b2 = new JRadioButton( Opcja 2 ); b2.setactioncommand(nazwa przycisku 2); ButtonGroup grupa = new ButtonGroup(); group.add(b1); group.add(b2); JToggleButton przycisk który pozostaje wciśnięty lub nie
Pole wyboru (JCheckBox) Wybór z możliwością zaznaczenia kilku pól Klasa pochodna po JAbstractButton Konstruktory jak w klasie JButton, dodatkowy argument boolean zaznacza/odznacza pole Metoda setselected(boolean) zaznacza/odznacza pole 38
Pole wyboru - przykład JCheckBox cb1 = new JCheckBox("HTML"), cb2 = new JCheckBox("JavaScript"), cb3 = new JCheckBox("Java", true); Container k = getcontentpane(); k.setlayout(new GridLayout(0,1)); k.add(cb1); k.add(cb2); k.add(cb3); cb1.setselected(true); 39
Pole wyboru - przykład 40
Pole tekstowe (JTextField) Jednowierszowe pole tekstowe z możliwością edycji Niektóre konstruktory JTextField(String napis) JTextField(String napis, int il_kolumn) JTextField(il_kolumn) 41
Pole JPasswordField Do tworzenia pól tekstowych z zamaskowanym napisem Konstruktory - jak w klasie JtextField public void setechochar(char c) 42
Lista rozwijana (JComboBox) Lista rozwijana przy aktywacji Można wybrać tylko jeden element z listy Elementy wyświetlane np. teksty, ikony Zaznaczanie elementu metoda setselectedindex(int) 43
Lista rozwijana - przykład String[] tab = {"HTML", "JavaScript", "Java"}; JComboBox cmb = new JComboBox(tab); Container k = getcontentpane(); k.setlayout(new FlowLayout()); k.add(cmb); cmb.setselectedindex(2); 44
Lista JList Zawierają grupę pozycji prezentowanych w kolumnie lub kilku kolumnach Umieszczana na panelu przesuwnym (JScrollPane) Wykorzystuje model do przechowywania informacji o pozycjach (DefaultListModel, AbstractListModel, ListModel) DefaultListModel listmodel = new DefaultListModel(); listmodel.addelement("pozycja1"); listmodel.addelement("pozycja2"); listmodel.addelement("pozycja3"); JList list = new JList(listModel); list.setselectionmode(listselectionmodel.single_interval_selecti ON); //SINGLE_SELECTION lub MULTIPLE_INTERVAL_SELECTION list.setlayoutorientation(jlist.horizontal_wrap);//vertical, VERTICAL_WRAP list.setvisiblerowcount(-1); //ile wierszy ma być widocznych; -1 -ile się zmieści (jeśli jeden wszystkie pozycje poziomo) jscrollpane1.setbounds(new Rectangle(18, 15, 169, 190)); contentpane.add(jscrollpane1, null); jscrollpane1.getviewport().add(list, null); 45
Lista JList Zaznaczenie elementu lista.setselectedindex(index) Zwrócenie elementu zaznaczonego elementu lista.getselectedindex() Usunięcie z listy listmodel.remove(index); Wstawienie elementu listmodel.insertelementat( Pozycja,index); 46
Tabela JTable String[] columnnames = {"Lp.", "Nazwisko", "Imie", "Wiek", "Klient specjalny"}; Object[][] data = {{new Integer(1), "Kowalski", "Piotr", new Integer(25), new Boolean(false)}, {new Integer(2), "Nowak", "Paweł", new Integer(32), new Boolean(true)}, {new Integer(3), "Wiśniewski", "Adam", new Integer(41), new Boolean(false)}}; JTable jtable1 = new JTable(data, columnnames); jscrollpane2.setbounds(new Rectangle(9, 155, 456, 80)); contentpane.add(jscrollpane2, null); jscrollpane2.getviewport().add(jtable1, null); 47
Tabela JTable Daj indeksy wybranych wierszy int[] tabelka.getselectedrows() Daj indeksy wybranych kolumn int[] tabelka.getselectedcolumns() Ustaw wartość tabelka.setvalueat(object, int row, int column) Zwróć wartość tabelka.getvalueat(int row, int column) 48
import javax.swing.tree.*; Tabela JTree DefaultMutableTreeNode korzen = new DefaultMutableTreeNode("Korzeń"); DefaultMutableTreeNode galaz1 = new DefaultMutableTreeNode("Gałąź 1"); korzen.add(galaz1); DefaultMutableTreeNode lisc1 = new DefaultMutableTreeNode("Liśc 1"); galaz1.add(lisc1); DefaultMutableTreeNode galaz2 = new DefaultMutableTreeNode("Gałąź 3"); korzen.add(galaz2); DefaultMutableTreeNode lisc2 = new DefaultMutableTreeNode("Lisc 2"); galaz2.add(lisc2); jtree1 = new JTree(korzen); DefaultMutableTreeNode wezel = (DefaultMutableTreeNode) jtree1.getlastselectedpathcomponent(); 49
Tworzenie menu Pasek menu JMenuBar Komponenty zdolne do wyświetlania menu - zawierają metodę setjmenubar() Menu rozwijane, umieszczane na pasku - JMenu Element menu rozwijanego JMenuItem 50
Tworzenie menu - przykład JMenuBar pasek = new JMenuBar(); JMenu menu1 = new JMenu("Plik"); JMenuItem[] elem = { new JMenuItem("Nowy"), new JMenuItem("Otwórz"), new JMenuItem("Zapisz")}; setjmenubar(pasek); pasek.add(menu1); for(int i=0; i<elem.length; i++) menu1.add(elem[i]); 51
Tworzenie menu - przykład 52
Klasa JMenuItem Pochodna po JAbstractButton; tworzenie elementów menu jak przycisków, np. ImageIcon rys = new ImageIcon("open.gif"); JMenuItem[] elem = { new JMenuItem("Nowy"), new JMenuItem("Otwórz", rys), new JMenuItem("Zapisz") }; 53
Inne klasy menu Klasy dziedziczące po JMenuItem JMenu tworzy menu kaskadowe JCheckBoxMenuItem dodaje pola wyboru JRadioButtonMenuItem dodaje przyciski wyboru menuitem = new JmenuItem("Tekst i ikonka", new ImageIcon("ikonka.gif")); Specjalne menu tzw. kontekstowe (JPopupMenu), niewidzialne dopóki użytkownik nie wykona pewnej czynności (tworzenie jak JMenuBar) popup = new JPopupMenu(); menuitem = new JMenuItem("A popup menu item"); menuitem.addactionlistener(this); popup.add(menuitem); 54
Inne komponenty Swingu JToggleButton przycisk z dwoma stanami (wciśnięty/zwolniony) JList lista pojedynczego/wielokrotnego wyboru JSpinner - pole umozliwiające zmianę wartości w górę lub w dół JTextArea wielowierszowe pole tekstowe JTextEditor umożliwia formatowanie tekstu JSlider - suwak JProgressBar pasek postępu JScrollBar pasek przewijania JTable - tablica JTree drzewo (np. katalogów) JColorChooser paleta kolorów JFileChooser lista plików 55
Inne komponenty Swingu 56
Podpowiedzi Dodawanie podpowiedzi do komponentu GUI metoda settooltiptext(string) klasy JComponent Przykład JButton p = new JButton("OK"); p.settooltiptext("uruchamia program"); 57
Kontenery Swingu Kontenery podstawowe aplet (JApplet) ramka (JFrame) okno komunikatów (JOptionPane) 58
Kontenery Swingu Kontenery ogólnego przeznaczenia panel (JPanel) panele specjalne (JScrollPane, JSplitPane, JTabbedPane) okno dialogowe (JDialog) pasek narzędziowy (JToolbar) 59
Kontenery Swingu Kontenery specjalnego przeznaczenia, np. JDesktopPane JInternalFrame JRootPane JLayeredPane 60
Ramka (JFrame) Osobne okno specyficzne dla platformy, z wyraźnym obramowaniem, tytułem, przyciskiem zamykania itp. Domyślny zarządca rozkładu - BorderLayout Konstruktory JFrame() JFrame(String napis) 61
Ramka (JFrame) Domyślnie ramka niewidzialna Uczynienie ramki widzialną metoda setvisible(true) lub show() Ustalenie rozmiaru ramki metoda pack() najmniejszy możliwy rozmiar metoda setsize(int szer, int wys) nie zalecana 62
Aplet Ramka import javax.swing.*; import java.awt.*; public class Ramka extends JApplet { public void init() { JFrame win = new JFrame("Moje okno"); JLabel etykieta = new JLabel("Java"); win.getcontentpane().add(etykieta); win.pack(); win.setvisible(true); } } 63
Okno dialogowe (JOptionPane) Okno wyświetlające pewne informacje, umieszczane w ramce (blokuje używanie innych okien) Rodzaje okien dialogowych ConfirmDialog okno potwierdzenia InputDialog okno wprowadzania tekstu MessageDialog komunikat OptionDialog okno z wyborem opcji 64
Okno dialogowe (JOptionPane) Tworzenie okna dialogowego odpowiednia metoda JOptionPane.showXxDialog(Component, String); Metody klasy JOptionPane przeciążone, możliwość zmiany tytułu, napisu na przycisku, ikony itp. 65
Przykłady okien komunikatów JOptionPane.showMessageDialog(win, "Koniec!"); JOptionPane.showMessageDialog(win, "Problem!", "UWAGA", JOptionPane.ERROR_MESSAGE); 66
Przykłady okien komunikatów Object[] possibilities = {"ham", "spam", "yam"}; String s = (String)JOptionPane.showInputDialog( frame, "Complete the sentence:\n" + "\"Green eggs and...\"", "Customized Dialog", JOptionPane.PLAIN_MESSAGE, icon, possibilities, "ham"); http://java.sun.com/docs/books/tutorial/uiswing/components/dialog.html#input 67
Panel (JPanel) Najprostszy kontener, domyślnie nieprzezroczysty Umożliwia rysowanie Domyślny zarządca rozkładu - FlowLayout 68
Panel (JPanel) Ustalenie, że panel ma być kontenerem pośrednim metoda setcontentpane() kontenera podstawowego, np. JPanel panel = new JPanel(); contentpane.setlayout(new BorderLayout()); contentpane.setborder(obramowanie); contentpane.add(etykieta); JApplet.setContentPane(panel); 69
HTML w komponentach Swing jbutton1 = new JButton("<html><center><b><u>W</u> yłącz</b><br>"+ "<font color=#00ff00>wszystkie</font><br>"+ "<i><b><font color=#ff0000>opcje</font> </b></i>"); jbutton1.setbounds(new Rectangle(372, 35, 98, 78)); 70
Aplikacje graficzne Mogą wykorzystywać wszystkie możliwości Swingu Używają kontenera JFrame - dziedziczenie lub tworzenie w metodzie main() 71
Aplikacja AplikSwing import javax.swing.*; import java.awt.*; public class AplikSwing { public static void main(string[] args){ JFrame ramka = new JFrame("Swing!!!"); Container k = ramka.getcontentpane(); k.setlayout(new GridLayout(0,1)); k.add(new JLabel("Program w Swingu")); k.add(new JButton("OK")); ramka.pack(); ramka.setvisible(true); } } 72
Zmodyfikowana aplikacja AplikSwing (cz. 1) import javax.swing.*; import java.awt.*; public class AplikSwing extends JFrame { AplikSwing(String tytul) { super(tytul); Container k = getcontentpane(); k.setlayout(new GridLayout(0,1)); k.add(new JLabel("Program w Swingu")); k.add(new JButton("OK")); } 73
Zmodyfikowana aplikacja AplikSwing (cz. 2) public static void main(string[] args) { AplikSwing ramka = new AplikSwing("Swing!!!"); ramka.pack(); ramka.setvisible(true); } } 74