Swing
Curs 9
Cuprins Introducere
Arhitectură
Modelul root pane container
Fire de execuţie Swing
Componente
AWT – Abstract Windows Toolkit Primul API Java utilizat pentru construirea de aplicaţii GUI
Oferă Mecanism robust de tratare a evenimentelor Manageri de layout
Dezavantaje: Portabilitate
Limitări legate de modul nativ în care se generează componentele (ex. pe Window foloseşte DirectX pentru generarea componentelor)
Facilităţi Nu suportă toate componentele (ex. tooltips, icoane)
Swing Un set de componente grafice customizabile al căror look-
and-feel este stabilit la runtime
Prima versiune oficială 1998
Versiune Java > 1.1.5
Corectează deficienţele AWT
Numele componentelor încep cu “J”
Noutăţi Swing vs AWT Acţiuni
Model de sincronizare al acţiunilor Tooltips Timers
Util pentru animaţie Event dispathcer thread Proprietăţi client Keyboard shortcuts
Managementul focusului, mnemonice şi acceleratori pentru meniuri, keymaps Contururi (borders) Icoane Cursori Double-buffering Containerul Box
Dimensiunile minime, maxime şi preferate ale componentelor Ferestre de dialog simple Componente
JFileChooser, JColorChooser, JTable (TableModel), ...
Componente AWT/Swing Componentele AWT Componente heavyweight Sunt asociate cu componentele native denumite peers Au acelaşi comportament dar look and feel care depinde de
platformă java.awt
Componentele Swing Componente lightweight Modul în care sunt desenate (renderizate) este controlat de
JVM javax.swing
Componente AWT/Swing Diferenţe componente heavyweight/lightweight Componentele lightweight pot conţine pixeli transparenţi, componentele
heavyweight sunt opace
Componentele lightweight pot avea alta formă decât dreptunghiulară deoarece conţin pixeli transparenţi, în schimb componentele heavyweight sunt doar dreptunghiulare
Evenimentele de mouse în cazul componentelor lightweight sunt tratate prin intermediul componentelor părinte, în schimb în cazul componentelor heavyweight nu sunt tratate prin intermediul componentelor părinte
În versiunile de Java mai mici de 1.7, când o componentă leightweight se suprapune pe una heavyweight, componenta heavyweight este totdeuna deasupra
Cuprins Introducere
Arhitectură
Modelul root pane container
Fire de execuţie Swing
Componente
Model View Controller Şablon arhitectural care separă nivelul de prezentare
de logica de business
Componentele Swing folosesc patternul MVC Model
Încapsulează starea datelor pentru fiecare componentă View
Modul în care se vede componenta pe ecran
Controler Modul în care interacţionează componenta cu evenimentele (tastatură, mouse, focus, etc)
Model
Controller
View
Model View Controller Şablonul este puţin diferit faţă de cel clasic Nu există o separare clară între View şi Controller Separarea de model este clară
Model View Controller MV/C
Pentru componentele mai simple se foloseşte de obicei modelul default
MVC Componente mai complexe
JList JTable JTree
JComponent
Swing Model(s)
View
Controller reporteză
referă la
modifică
Modelul Fiecare componentă are clasa ei de model JTable are TableModel
Modelul este responsabil cu oferirea de date componentei
De fiecare dată când modelul se modifică se notifică toţi ascultătorii prin lansarea unui eveniment
Putem folosi modele Default Implementa propriile modele, dacă ne asigură un mai bun control al
datelor în interiorul componentei
View Fiecare componentă are propria clasă de view Responsabilă cu desenarea componentei Numite UI Delegate
Exemplu: ButtonUI, SliderUI, etc
Unele din proprietăţile viewului se regăsesc în clasa Component Exemplu: proprietăţile de font, background, mărime
Root Pane Gestionează Content pane Bara de meniuri Alte containăre
Cuprins Introducere
Arhitectură
Modelul root pane container
Fire de executie Swing
Componente
Regula threadu-ului Unic Metodele componentelor AWT sunt thread safe accesul concurent la componente nu le vor afecta starea
Componentele Swing nu sunt thread safe din motive
de eficienţă Odată ce o componentă Swing este pregătită să primească
evenimente, tot codul care poate afecta sau depinde de starea componentei trebuie să fie executat în event dispatching thread
Unele din metode, de exemplu repaint(), revalidate(), invalidate(), metodele ce modifică listele de listeners, au rămas thread safe fiind tratate de event thread
Event-Handling Thread Event Thread este pornit automat de JVM când o
aplicaţie conţine componente grafice
Responsabil pentru apelul metodelor paint() actionPerformed() Restul de metode care se ocupă de tratarea acţiunilor
Permite modificarea sigură (safe) a componentelor
Regula threadu-ului Unic Rezolvarea problemei modificării componentelor de
un fir de execuţie extern Mecanism de adăugare a unei bucăţi de cod în coada de
evenimente Când thread-ul event ajunge la acest cod se blochează şi
execută codul
SwingUtilities public static void invokeLater( Runnable r)
Dacă nu se doresc rezultatele înainte de a contiunua cu restul de taskuri şi nu ne interesează când taskul se termină
public static void invokeAndWait( Runnable r) Dacă avem nevoie de rezultate înainte de a continua cu restul de
taskuri
Cuprins Introducere
Arhitectură
Modelul root pane container
Fire de executie Swing
Componente
Crearea unei aplicaţii Crearea:
Frame/JFrame Panel/JPanel Componente Listenere
Adăugarea: Listenere la componente Componente într-un panel Panel într-un frame
JPanel
JButton
Listener
JFrame
JLabel
Containere intermediare Containere intermediare JPane JScrollPane JSplitPane JTabbedPane
Utilizate pentru a grupa componente
Layoutul default FlowLayout
JPane Containerul intermediar de bază pentru orice interfaţă grafică
Cel mai des utilizat pentru a organiza un grup de componente
Panoul implicit al unei ferestre este contentPane, al cărui
layout implicit este BorderLayout
Metode Setare layout Gestionare componente (adăugare/ştergere) Setare border
JScrollPane Dă posibilitatea altor componente de a se derula (scroll)
dacă nu încap într-o zonă de dimensiune fixă Exemplu
JTextArea textArea = new JTextArea(5, 5); JScrollPane scrollableTextArea = new JScrollPane(textArea); scrollableTextArea.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); scrollableTextArea.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SC add(scrollableTextArea);ROLLBAR_ALWAYS);
JSplitPane Încapsulează două panouri alăturate separate printr-un marcaj
despărţitor (divider), permiţând vizualizarea simultană a două componente una lângă alta
Metode pentru adăugarea de componente setTopComponent() setLeftComponent() setBottomComponent() setRightComponent()
Exemplu
JPanel panel1 = new JPanel(); JPanel panel2 = new JPanel(); JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, panel1, panel2); splitPane.setDividerLocation(0.25);
JTabedPane Stivă de componente aşezate pe mai multe straturi
suprapuse
Metode addTab() removeTabAt() setSelectedIndex()
Nu este prezent în AWT Similar cu FlowLayout
JTabedPane Exemplu
JTabbedPane tabbedPane = new JTabbedPane(); ImageIcon icon = createImageIcon("images/middle.gif"); JComponent panel1 = makeTextPanel("Panel #1"); tabbedPane.addTab("Tab 1", icon, panel1,"Does nothing"); tabbedPane.setMnemonicAt(0, KeyEvent.VK_1); JComponent panel2 = makeTextPanel("Panel #2"); tabbedPane.addTab("Tab 2", icon, panel2, "Does twice as much nothing"); tabbedPane.setMnemonicAt(1, KeyEvent.VK_2); tabbedPane.setSelectedIndex(2); add(tabbedPane);
Componente Simple Etichete
Butoane
Borduri
Liste
Drop down list
Spinner
Etichete JLabel Poate interpreta cod HTML
Utile pentru a afişa Text Imagini
label1 = new JLabel("Image and Text", icon, JLabel.CENTER); label1.setVerticalTextPosition(JLabel.BOTTOM); label1.setHorizontalTextPosition(JLabel.CENTER); label2 = new JLabel("Text-Only Label"); label3 = new JLabel(icon);
JLabel l = new JLabel("<html><center><b>Label</b><br><font color=#ff00ff>HTML Format</font></html>");
Butoane JButton
JCheckbox
JRadioButton
JMenuItem
JCheckBoxMenuItem
JRadioButtonMenuItem
JToggleButton
Butoane Realizează acţiuni
Pot fi grupate ButtonGroup
Se pot adăuga Imagini HTML text Mnemonice
Stările butoanelor Selectat (selected)
Apăsat (pressed)
Derulat (rollover)
Armat (armed)
Activat (enabled)
Exemple Butoane Simple Butoane - new JButton("Buton Simplu"); Adăugare de icoane
Modificarea modului cum arată Utilizare HTML - add(new
JButton("<html><b><u>T</u>wo</b><br>lines</html>"));
Radio/CheckboxButtons
btnCuPoza = new JButton("Buton cu Poza"); btnCuPoza.setIcon(new ImageIcon(getImage(getCodeBase(), "../img/butoane/icon1.JPG"))); btnCuPoza.addActionListener(this); btnCuPoza.setHorizontalTextPosition(SwingConstants.LEFT); btnCuPoza.setMnemonic(KeyEvent.VK_P);
Exemple Butoane Simple Modificarea modului cum arată
btn = new FancyButton(new ImageIcon(getImage(getCodeBase(), "../img/butoane/icon1.JPG")), new ImageIcon(getImage( getCodeBase(), "../img/icon2.JPG")), new ImageIcon(getImage(getCodeBase(), "../img/butoane/icon3.JPG"))); btn.setText("FancyButton"); btn.setIcon(new ImageIcon(getImage(getCodeBase(), "../img/butoane/icon1.JPG")));
public class FancyButton extends JButton { public FancyButton(Icon icon, Icon pressed, Icon rollover) { super(icon); setFocusPainted(false); setRolloverEnabled(true); setRolloverIcon(rollover); setPressedIcon(pressed); setBorderPainted(false); setContentAreaFille(false); }
Exemple Radio/CheckboxButtons
r1 = new JRadioButton("Icoana vizibila cand butonului nu este afisat"); r1.setActionCommand("1"); r1.setSelected(true); panelButone.add(r1); r2 = new JRadioButton("Icoana vizibila la trecerea peste buton"); r2.setActionCommand("2"); panelButone.add(r2); r3 = new JRadioButton("Icoana vizibila la apasarea butonuluit"); panelButone.add(r3); ButtonGroup group = new ButtonGroup(); group.add(r1); group.add(r2); group.add(r3); JCheckBox cb1 = new JCheckBox("Rosu");
Exemplu ToolgeButton JToggleButton redButton = new JToggleButton("red");
Borduri Borders
Nu sunt derivate din JComponent, nu li se pot adăuga ascultători
Borduri standard
CompoundBorder EmptyBorder EtchedBorder LineBorder MatteBorder SoftBevelBorder TitledBorder
BorderFactory
setBorder()
Borduri
Borduri Exemplu
Border outline = BorderFactory.createLineBorder(Color.black); JLabel northLabel = new JLabel("NORTH"); northLabel.setHorizontalAlignment(SwingConstants.CENTER); northLabel.setBorder(outline);
JList Permite selectarea unui/sau mai multor elemente dintr-o listă SINGLE_SELECTION SINGLE_INTERVAL_SELECTION MULTIPLE_INTERVAL_SELECTION
Obiectele sunt afişate prin apelul la metoda toString() Excepţie: clasa Icon
Modelul DefaultListModel AbstractListModel
Evenimente ListSelectionListener
JComboBox Combină un buton cu o listă (intern popup)
Modele de date DefaultComboBoxModel MutableComboBoxModel
Permite operaţii de adăugare/ştergere/modificare
Evenimente ChangeListener
Tipuri Combobox Combobox editabil
Exemplu final JComboBox<Culoare> cb = new JComboBox<Culoare>(); cb.addItem(new Culoare ("Rosu", Color.red)); cb.addItem(new Culoare ("Gri",Color.gray)); cb.addItem(new Culoare ("Verde",Color.green)); cb.addItem(new Culoare ("Albastru",Color.blue)); cb.addItemListener(new ItemListener() { @Override public void itemStateChanged(ItemEvent ie) { Culoare color = (Culoare) cb.getSelectedItem(); lText.setBackground(color.color); lText.updateUI(); } });
JSpinner Reprezintă o linie de text care permite utilizatorului să
selecteze o valoare dintr-o secvenţă de valori
Selectare Utilizând săgeţi Introducerea directă a unei valori
Modele SpinnerListModel AbstractSpinnerModel SpinnerDateModel SpinnerModel SpinnerNumberMode
Componente complexe Componente text
Tabele
Arbori
Componente Text Afişează şi permit editarea textului
Componente Text Conţinutul este menţinut într-o instanţă a interfeţei
document PlainDocument StyledDocument
Sistemul de copiere/lipire implementat în
JTextComponent copy() cut() select(int pozInt, int pozFin) selectAll()
Tabele JTable
Afişarea datelor în tabele
Proprietăţi
Utilizatorul poate să Selecteze linii, coloane sau capul tabelului (header) Reordoneze coloane prin mutarea header-ului Redimensioneze coloane prin mutarea marginii dintre coloane Editeze valorile celulelor Sorteze coloanele pe baza conţinutului Filtreze coloanele pe baza conţinutului
Codul poate să
Modifice valorile celulelor Adauge/şterge/mutearea de coloane Customizeze modul în care se desenează tabelul Customizeze modul de editare al tabelului
Tabele - Clase relaţionate
Tabele JTable conţine multe proprietăţi care pot fi customizate, precum editarea
sau desenarea celulelor, dar de asemenea oferă valori default pentru aceste
O componentă Jtable este formată din: Linii de date Coloane cu date Headere de coloane Un editor dacă dorim ca celulele să fie editabile TableModel, de obicei subclasă a clasei AbstractTableModel care conţine datele
tabelului TableColumnModel, de obicei DefaultTableColunModel, care controlează
comportamentul coloanelor tabelului şi ne dă acces la ele ListSelectionModel, de obicei DefaultListSelectionModel, care menţine informaţii
despre liniile selectate din tabel TableCellRenderere, de obicei DefaultTableCellRenderer, care oferă informaţii
despre modul în care se desenează celulele MultipleTableColums, stochează informaţii despre fiecare coloană JTableHeader afişează headerul
TableModel Gestioneză datele afişate în tabel Metode Class getColumnClass(int columnIndex)
Utilizat de renderer şi editor
boolean isCellEditable(int rowIndex, int columnIndex) Object getValueAt(int rowIndex, int columnIndex) void setValueAt(Object aValue, int rowIndex, int
columnIndex) Apelată de JTable când au loc editări
void addTableModelListener (TableModelListener l) Notificări ale datelor şi sturucturi tabelului
TableModel AbstractTableModel defaulats
Clasa obiectului este raportată ca fiind de tip Object Coloanele au un nume default dacă nu se specifică unul Celulele nu sunt editabile
Trebuie suprascrise metodele
int getRowCount(); int getColumnCount(); Object getValueAt(int rowIndex, int columnIndex
TableModel DefaultTableMode Stochează datele în vectori
Un vector pentru fiecare coloană
defaulats
Clasa obiectului este raportată ca fiind de tip Object Coloanele au un nume default dacă nu se specifică unul Celulele nu sunt editabile
ColumModel Încapsulează informaţii despre:
Valorile header-elor Dimensiuni Modul de desenare Modul de editare Permite redimensionarea coloanelor
JTree Permite vizualizarea structurilor arborescente
Are un singur nod rădăcină
Mecanism de selecţie asemănător cu al componentei JList
Dialoguri default JOptionPane
JFileChooser
JColorChooser
JOptionPane Permite realizarea facilă de dialoguri simple Afişarea unui mesaj Punerea unei întrebări Introducerea unei valori
Ferestre modale Blochează aplicaţia în aşteptarea unui răspuns
JOptionPane Tipuri Mesaj
showConfirmDialog()
Confirmare showInputDialog()
Intrare
showMessageDialog()
Opţiune showOptionDialog()
JFileChooser Componentă care permite navigarea prin sistemul de
fişiere Salvare Deschidere
JFileChooser files = new JFileChooser(DEFAULT_DIRECTORY); int result = files.showSaveDialog(frame); File f = files.getSelectedFile();
File Chooser Filtre pentru fişiere FileNameExtensionFilter Crearea propriului filtru prin extinderea clasei FileFilter
FileFilter filter = new FileNameExtensionFilter (“Text files (*.txt)”, ” txt” ); files.addChoosableFileFilter(filter);
JColorChooser Permite alegerea de culori
Moduri disponibile Swatches HSV —Hue-Saturation-Value RGB —Red-Green-Blue HSL —Hue-Saturation-Lightness CMYK – Crayn-Magenda-Yellow-Black
Componente pentru progres şi derulare JSlider
JScrollBar
JProgressBar
JToolTip
Slider JSlider
Utilizat în special dacă avem nevoie să alegem valori din
intervale de numerice cunoscute
Proprietăţi Orientation Extent
Numărul de valori sărite prin folosirea tastelor pageUp şi pageDown minorTickSpacing majorTickSpacing paintTicks paintLabels inverted
Progress Bar JProgressBar
Folosită pentru a indica progresul unei operaţii
consumatoare de timp
Monitorizarea activităţii se face prin metoda setValue()
Bară de defilare JScrollBar
De obiecei se ataşează componentelor pentru a derula
mai uşor conţinutul
Proprietăţi Orientarea Locul unde este poziţionat iniţial indicatorul Mărimea indicatorului
ToolTip JToolTip
Ferestre care permit asocierea de informaţii textuale componentelor aplicaţiei
Vizibile când mouse-ul se află deasupra componentei
void setToolTipText( String text)
Se activează dacă mouseul rămâne 750 ms asupra componentei
Rămâne activat 4000 ms
Dacă intrăm, ieşim din componetă se activează în 500 ms
Perioadele de timp pot fi modificate prin intermediul clasei ToolTipManager
setInitialDelay(), setDismissDelay(), setReshowDelay()
Meniuri Java permite crearea de Bare de meniuri
JMenuBar,
Meniuri JMenu, JMenuItem, JSeparator, JCheckBoxMenuItem,
JRadioButtonMenuItem
Meniuri Popup JPopupMenu
Bare de acţiuni (tool bars) JToolBar
Componentele meniurilor
Meniuri Ierarhia de clase
Meniuri Evenimente
Mouse
Tastatură
Combinaţie de taste echivalentă (mnemonice) Prima literă din submeniu
Acceleratori Permit accesarea directă a unui submeniu
Construirea unui meniu Construire bară meniu:
MenuBar bara = new MenuBar();
Construire meniu Menu meniu = new Menu(“Exemplu”);
Construire elemente şi adăugare la meniu:
meniu.add(new MenuItem(“intrare 1”)); meniu.addSeparator(); meniu.add(new MenuItem(“intrare 2”));
Adăugarea fiecărui meniu la bara meniu:
bara.add(meniu);
Adăugarea barei de meniu la frame: Frame frame = new Frame(“Titlu”); frame.setMenuBar(bara);
Layout-uri Spring BoxLayout Componentele sunt aşezate sub forma unei stive una peste
alta şi pot fi afişate pe orizontală sau verticală GroupLayout Grupează ierarhic componente pentru a le poziţiona în
container SpringLayout Defineşte relaţii (constrângeri) direcţionale între muchiile
componentelor
Alte posibilităţi Crearea de layout customizat Poziţionarea absolută
Look & Feel Swing permite modificarea modului în care arată
componentele Look – se referă la modul cum arată componentele Feel – modul în care se comportă componentele
Tipuri CrossPlatformLookAndFeel
Java L&F - Metal SystemLookAndFeel
L&F nativ sitemului pe care rulează aplicaţia Synth
Creare propriului L&F prin intermediul fişierelor XML Multiplexing
Utilizarea de mai multe L&F în accelaşi timp
Exemple de setare L&F Specificare din program L&F java
UIManager.setLookAndFeel( UIManager.getCrossPlatformLookAndFeelClassName());
L&F platformei UIManager.setLookAndFeel(
UIManager.getSystemLookAndFeelClassName());
Specificarea din linia de comanda java -
Dswing.defaultlaf=com.sun.java.swing.plaf.windows.WindowsLookAndFeel MyAp
Creare de custom L&F Utilizare L&F Synth Programatic
Moştenirea clasei SynthStyleFactory
Fişiere XML
javax.swing.plaf.synth/doc-files/synthFileFormat.html
class MyStyleFactory extends SynthStyleFactory { public SynthStyle getStyle(JComponent c, Region id) { if (id == Region.BUTTON) { return buttonStyle; } else if (id == Region.TREE) { return treeStyle; } return defaultStyle; } }
Alte facilităţi Alte facilităţi
Gestionarea focusului
Dialoguri
Tipărirea tabelelor
Crearea de splash screens
Ferestre de dialog Dialog Box O fereastră de nivel înalt care are un tilu şi margini şi colecteză
informaţii de la utilizator
Modlă sau nemodală Modal Dialog Box Blochează inputul la ferestrele aplicaţei până când nu este închisă
Modeless Dialog Box Fereastră de dialog care permite operarea cu alate ferestre ale aplicaţiei
cât timp este deschisă
Ferestre de dialog Tipuri (java 1.6) Modeless
Nu blochează nici o altă fereastră când este vizibilă Document-modal
Blochează toate ferestrele din accelaşi document, cu excepţia ferestrelor din ierarhia de copii
Document - ierarhie de ferestre care au aceelaşi părinte Application-modal
Blochează toate ferestrele din aceeaşi aplicaţie, cu excepţia ferestrelor din ierarhia de copii
Toolkit-modal Blochează toate ferestrele din aceelaşi toolkit, cu excepţia ferestrelor din
ierarhia de copii Exclusion mode
Permite marcarea ferestrelor care nu vor fi blocate de o fereastă modală
Crearea de splash screens java -splash:images/splash.gif SplashDemo
final SplashScreen splash = SplashScreen.getSplashScreen(); if (splash == null) { System.out.println("SplashScreen.getSplashScreen() returned null"); return; } Graphics2D g = splash.createGraphics(); if (g == null) { System.out.println("g is null"); return; }
Concluzii Avantaje Swing:
Portabilitatea: conţine mai puţine elemente specifice platformei
Comportament: permite adăugarea unui comportament mai flexibil deoarece legăturile cu platforma nu mai sunt aşa de strânse
Proprietaţi: suportă mai multe proprietăţi ca icoane, tooltips pentru componente
Look and Feel: permite ca aplicaţia să arate la fel pe toate platformele (Windows, Solaris, ...)
Dezavantaje Swing:
Portabilitatea appleturilor: majoritatea browserelor nu includ clasele Swing, deci trebuie folosit un plugin Java
Performanţe: componentele Swing sunt mai lente decât AWT.
Look and Feel: chiar dacă componentele Swing sunt setate să folosescă look and feel-ul sistemului de operare pe care functionează, s-ar putea să nu arate ca şi componentele native.