Przygotował: Jacek Sroka
1
Java SE
Swing
Przygotował: Jacek Sroka
2
GUI w Javie
Abstract Window Toolkit (AWT)
●
podstawowy
(wspólny mianownik)
zbiór komponentów opartych na zarządcy okien
–
wspólny mianownik funkcjonalności ze wszystkich platform
●
rozbudowany model obsługi zdarzeń
●
klasy pomocnicze m.in. kształty, kolory i fonty
●
zarządcy układu
●
obsługa schowka
Przygotował: Jacek Sroka
3
GUI w Javie
Swing
●
to co w AWT plus
●
Javowa implementacja komponentów z AWT
●
rozbudowany zestaw komponentów zaimplementowanych w Javie
–
tylko komponenty najwyższego poziomu są oparte na zarządcy okien
–
ta sama funkcjonalność na wszystkich platformach
●
przełączalny wygląd i zachowanie (pluggable look and feel)
–
dość dobra ale nie idealna symulacja wyglądu zarządcy okien (nie korzysta z
akceleracji)
Przygotował: Jacek Sroka
4
GUI w Javie c.d.
●
Standard Widget Toolkit (SWT)
–
zapoczątkowany przez IBMa, rozwijany w ramach platformy Eclipse
–
opiera się na zarządcy okien tak ja AWT, ale nie ogranicza funkcjonalności
–
gorsza przenośność aplikacji (WORE vs WOTE)
Przygotował: Jacek Sroka
5
import
javax.swing.*;
public
class
WitajSwiecie {
private
static
void
utwórzGUI() {
//tworzenie nowego okna
JFrame frame =
new
JFrame(
"Okno WitajSwiecie"
);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//dodawanie etykiety z przywitaniem
JLabel label =
new
JLabel(
"Witaj świecie!"
);
frame.add(label);
//ustalanie wymiarów i wyświetlanie okna
//frame.pack(); //względem komponentów
frame.setSize(300,150);
frame.setVisible(
true
);
}
public
static
void
main(String[] args) {
//aby uniknąć zakleszczeń tworzenie GUI
//zlecamy do wątku obsługi zdarzeń
SwingUtilities.invokeLater(
new
Runnable() {
public
void
run() {
utwórzGUI();
}
});
}
}
Przykład
Przygotował: Jacek Sroka
6
Podstawowe komponenty
JLabel
●
wyświetla tekst lub obrazek
●
get/setText()
●
get/setIcon()
●
get/setHorizontalAlignment()
●
get/setVerticalAlignment()
●
get/setDisplayedMnemonic() – mnemonic to podkreślona
litera
●
get/setLabelFor() – komponent do którego zostanie
przeniesiony focus po wybraniu Alt+mnemonic
Przygotował: Jacek Sroka
7
Podstawowe komponenty
JButton
●
podobnie jak etykieta (i inne komponenty) posiada
get/setText(), get/setIcon(), get/setHorizontalAlignment(),
get/setVerticalAlignment(), get/setDisplayedMnenomic()
●
przycisk może zmieniać wygląd w zależności od swojego stanu
–
get/setDisabledIcon()
–
get/setDisabledSelectedIcon()
–
get/setIcon()
–
get/setPressedIcon()
–
get/setRolloverIcon()
–
get/setRolloverSelectedIcon()
–
get/setSelectedIcon()
●
akcję dowiązujemy przy pomocy zdarzeń
Przygotował: Jacek Sroka
8
Podstawowe komponenty
JTextField
●
get/setText()
JFrame
●
kontener na inne komponenty
●
łącznik do systemu operacyjnego (systemu okien)
–
get/setTitle() – tytuł okienka
–
get/setState() – minimalizacja/maksymalizacja
–
is/setVisible() – widoczność na ekranie
–
get/setLocation() – umiejscowanie na ekranie
–
get/setSize() – rozmiar
–
add() – dodanie komponentu
Przygotował: Jacek Sroka
9
Drugi przykład
import
javax.swing.*;
public
class
AWitajŚwiecie
extends
JFrame {
JLabel
jLabel
;
JTextField
jTextField
;
JButton
jButton
;
public
AWitajŚwiecie()
{
super
();
this
.setSize(300, 200);
this
.getContentPane().setLayout(
null
);
this
.add(getJLabel(),
null
);
this
.add(getJTextField(),
null
);
this
.add(getJButton(),
null
);
this
.setTitle(
"WitajSwiecie"
);
this
.setVisible(
true
);
}
Przygotował: Jacek Sroka
10
private
javax.swing.JLabel getJLabel() {
if
(jLabel ==
null
) {
jLabel =
new
javax.swing.JLabel();
jLabel.setBounds(34, 49, 53, 18);
jLabel.setText(
"Imię:"
);
}
return
jLabel;
}
private
javax.swing.JTextField getJTextField() {
if
(jTextField ==
null
) {
jTextField =
new
javax.swing.JTextField();
jTextField.setBounds(96, 49, 160, 20);
}
return
jTextField;
}
private
javax.swing.JButton getJButton() {
if
(jButton ==
null
) {
jButton =
new
javax.swing.JButton();
jButton.setBounds(103, 110, 71, 27);
jButton.setText(
"OK"
);
}
return
jButton;
}
public
static
void
main(String[] args) {
new
AWitajŚwiecie();
}
Przygotował: Jacek Sroka
11
Problemy
●
Bezwzględne rozmiary i współrzędne
–
jak to będzie wyglądać na innych platformach?
●
Jak zakończyć aplikację?
–
DO_NOTHING_ON_CLOSE
–
HIDE_ON_CLOSE (domyślne dla JDialog i JFrame) – ukrywa okno
–
DISPOSE_ON_CLOSE (domyślne dla JInternalFrame) – ukrywa i
zwalnia zasoby; jeżeli to było ostatnie okno to VM może zakończyć
działanie
–
EXIT_ON_CLOSE kończy aplikację przy pomocy System.exit(0)
●
Czy rozszerzać JFrame i pamiętać komponenty jako atrybuty?
Przygotował: Jacek Sroka
12
Zarządcy układu
●
BorderLayout
–
używany domyślnie przez główne komponenty (JApplet, JDialog i
JFrame)
●
zmiana metodą setLayout(LayoutManager)
–
rejony: prawo, lewo, góra, dół, środek (domyślnie)
–
dodanie nowego komponentu do rejonu już posiadającego zawartość
spowoduje jej podmianę
●
FlowLayout
–
układa komponenty od lewej do prawej
–
dozwala komponentom na preferowany
rozmiar, nawet jak nie będą przez to
widoczne w całości
Przygotował: Jacek Sroka
13
Zarządcy układu c.d.
●
GridLayout
–
komponenty umieszczane są w komórkach siatki
–
wszystkie komponenty mają taki sam rozmiar
●
I wiele innych...
–
BoxLayout – wiersz lub kolumna (można zagnieżdżać)
–
GridBagLayout – duże możliwości, skomplikowany
–
SpringLayout – rozmieszczenie wyznaczone przez więzy (sprężyny z
minimalną, maksymalną i optymalną długością)
–
CardLayout – przełączalne karty
Przygotował: Jacek Sroka
14
Zarządcy układu c.d.
Przygotował: Jacek Sroka
15
Jeszcze trochę komponentów
●
JComboBox
–
pozwala wybrać max 1 element
–
addItem() – dodaje element do grupy
–
get/setSelectedIndex()– manipuluje stanem
–
get/setSelectedItem() – zwraca/ustawia wybrany element
–
removeAllItems() – usuwa wszystkie elementy
–
removeItem() – usuwa konkretny element
●
JPasswordField
–
podobny do JTextField
–
get/setEchoChar() – wyświetlany znak
–
getText() – zwraca napis (przy heap dump teoretycznie można go odczytać)
–
getPassword() – zwraca char[]
Przygotował: Jacek Sroka
16
Jeszcze trochę komponentów c.d.
●
JCheckBox i JRadioButton
–
JRadioButton daje wykluczający się wybór
–
add() – dodaje checkbox lub przycisk do grupy
–
getElements() – zwraca wszystkie komponenty
grupy do iteracji
●
JOptionPane
–
gotowiec do wyskakujących okienek
Przygotował: Jacek Sroka
17
Jeszcze trochę komponentów c.d.
●
JMenu/JMenuItem/JMenuBar
–
przy pomocy setJMenuBar() ustawia się JMenuBar dla ramki
–
JMenu zawiera JMenuItem lub inne JMenu
–
JMenuItem się wybiera
–
dla JMenuItem można ustawić skrót
–
dla JMenu i JMenuItem można ustawiać mnemoniki
–
Wspólne metody JMenuItem oraz jego podklasy JMenu:
●
get/setAccelerator() – ustawia skrót postaci Ctrl+klawisz
●
get/setText() – tekst wyświetlany w menu
●
get/setIcon() – ikona wyświetlana w menu
–
Metody JMenu:
●
add() – dodaje element lub podmenu
Przygotował: Jacek Sroka
18
Jeszcze trochę komponentów c.d.
●
JSlider
–
wygodne pobieranie wartości całkowitych
z zadanego zakresu
–
get/setMinimum()
–
get/setMaximum()
–
get/setOrientation() – pion lub poziom
–
get/setValue()
●
JSpinner
–
umożliwia wybór z ciągu wartości, np. liczb, dat, kolorów
(trochę podobny do JSlider i JComboBox)
–
get/setValue() – początkowa wartość jako liczba całkowita
–
getNextValue() – wartość po kliknięciu strzałki w górę
–
getPrevioudValue() – wartość po kliknięciu strzałki w dół
Przygotował: Jacek Sroka
19
Jeszcze trochę komponentów c.d.
●
JToolBar
–
pasek narzędziowy, może pływać
–
działa jak paleta na inne komponenty
–
is/setFloatable()
●
JToolTip
–
podpisy do wszystkich innych komponentów
–
sami nie tworzymy tylko ustawiamy metodą setToolTip()
Przygotował: Jacek Sroka
20
Jeszcze trochę komponentów c.d.
●
JTextArea
–
wieloliniowe pole tekstowe
–
is/setLineWrap() – czy załamywać linie
–
is/setWrapStyleWord() –
czy załamywać słowa
●
JScrollPane
–
przykład Dekoratora
–
getHorizontalScrollBar() – zwraca zawarty
obiekty JScrollBar
–
getVerticalScrollBar() – analogicznie
–
get/setHorizontalScrollBarPolicy() –
Always, Never lub Needed.
–
get/setVerticalScrollBarPolicy() –
analogicznie
Przygotował: Jacek Sroka
21
Jeszcze trochę komponentów c.d.
●
JList
–
podobna do JComboBox,
ale umożliwia wybór wielu wartości
–
najlepiej opakowywać w JScrollPane
–
get/setSelectedIndex() – indeks wiersza
lub int[]
–
get/setSelectionMode() – tryb wyboru
–
setListData() – dane dla listy
–
aet/setSelectedValue() – zaznaczony obiekt
Przygotował: Jacek Sroka
22
Jeszcze trochę komponentów c.d.
●
JTable
●
JTree
Przygotował: Jacek Sroka
23
Obsługa zdarzeń
●
Wzorzec Obserwator (ang. Observer)
–
Wydawca-Prenumerator (ang. Publish-Subscribe)
–
Delegowanie obsługi zdarzeń (ang. Delegation Event Model)
●
Konwencja nazewnicza
–
addActionListener(ActionListener) i
removeActionListener(ActionListener)
–
actionPerformed(ActionEvent)
●
Kod obsługi zdarzeń wykonywany jest przez wątek
koordynujący zdarzenia
–
długotrwałe operacje zamulają interfejs
–
można używać SwingUtilities.invokeLater()
–
uwaga na zakleszczenia przy przebudowywaniu interfejsu z innego wątku
Przygotował: Jacek Sroka
24
public
class
ZliczanieKliknięć
extends
JFrame {
Integer licznikKliknięć = 0; JLabel etykieta;
class
ZwiększanieLicznika
implements
ActionListener {
public
void
actionPerformed(ActionEvent e) {
//obiekt klasy wewnętrznej ma dostęp do skład. obiektu klasy otaczającej
licznikKliknięć++;
etykieta.setText(
"Dotychczas kliknąłeś "
+ licznikKliknięć +
(licznikKliknięć == 1 ?
" raz"
:
" razy"
));
}
}
ZliczanieKliknięć() {
super
(
"Okno ZliczanieKliknięć"
);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel =
new
JPanel();
panel.setLayout(
new
GridLayout(3, 0));
JButton przycisk =
new
JButton(
"Kliknij"
);
przycisk.addActionListener(
new
ZwiększanieLicznika());
panel.add(przycisk);
etykieta =
new
JLabel(
"Jeszcze nie kliknięto ani razu"
);
panel.add(
new
JPanel());
//pusty panel zapewnia odstęp
panel.add(etykieta);
//puste obramowanie odsuwa komponenty od krawędzi
panel.setBorder(BorderFactory.createEmptyBorder(30,60,10,60));
add(panel);
//...
Przygotował: Jacek Sroka
25
Najważniejsze rodzaje zdarzeń
●
ActionListener – kliknięcie przycisku, wybór pozycji z menu,
zaakceptowanie wartości w polu tekstowym
–
actionPerformed(ActionEvent e)
●
KeyListener – obsługa klawiatury: wciśnięcie, puszczenie i kliknięcie
klawisza
–
istnieje klasa adapter KeyAdapter
–
keyPressed(KeyEvent e)
–
keyReleased(KeyEvent e)
–
keyTyped(KeyEvent e)
Przygotował: Jacek Sroka
26
Najważniejsze rodzaje zdarzeń
●
MouseListener – obsługa myszki: wciśnięcie przycisku, puszczenie
przycisku, kliknięcie, najechanie i opuszczenie
–
istnieje klasa adapter MouseMotionListener
–
mouseClicked(MouseEvent e)
–
mouseEntered(MouseEvent e)
–
mouseExited(MouseEvent e)
–
mousePressed(MouseEvent e)
–
mouseReleased(MouseEvent e)
●
MouseMotionListener – wykrywanie ruchu kursora
–
istnieje klasa adapter MouseMotionAdapter
–
mouseDragged(MouseEvent e)
–
mouseMoved(MouseEvent e)
Przygotował: Jacek Sroka
27
Najważniejsze rodzaje zdarzeń
●
TextListener – dotyczy komponentów rozszerzających
JTextComponent (np. JTextArea i JTextField); zachodzi gdy zmienił
się tekst
–
textValueChanged(TextEvent e)
●
WindowListener – aktywacja/dezaktywacja,
minimalizacja/maksymalizacja, itp.
–
istnieje klasa adapter WindowAdapter
–
windowActivated(WindowEvent e)
–
windowClosed(WindowEvent e)
–
windowClosing(WindowEvent e)
–
windowDeactivated(WindowEvent e)
–
windowDeiconified(WindowEvent e)
–
windowIconified(WindowEvent e)
–
windowOpened(WindowEvent e)
Przygotował: Jacek Sroka
28
Modele
Zamiast żmudnie zarządzać danymi niektórych komponentów
wygodniej podłączyć do nich model
●
JComboBox – jakie są możliwości wyboru i ile ich jest
●
JSpinner – co wyświetlić i jakie są poprzednie i wcześniejsze możliwości
●
JList – jaki tekst opisuje poszczególne możliwości wyboru
●
JTable – liczba kolumn i wierszy, ich etykiety, klasy kolumn, tekst każdej
komórki
●
JTree – struktura drzewa
Przygotował: Jacek Sroka
29
Modele – przykład
super
(
"Okno ComboBoxModel"
);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String[] data = {
"Ala"
,
"Ola"
,
"Ela"
,
"Ula"
};
MyComboModel model =
new
MyComboModel(java.util.Arrays.asList(data));
JComboBox cb1 =
new
JComboBox();
JComboBox cb2 =
new
JComboBox();
cb1.setModel(model);
cb2.setModel(model);
setLayout(
new
FlowLayout());
add(cb1);
add(cb2);
setSize(300, 150);
setVisible(
true
);
Przygotował: Jacek Sroka
30
Modele – przykład c.d.
class
MyComboModel
implements
ComboBoxModel {
private
List data =
new
ArrayList();
private
int
selected
= 0;
public
MyComboModel(List list) {
data = list; }
public
void
setSelectedItem(Object o) {
selected
= data.indexOf(o);
}
public
Object getSelectedItem() {
return
data.get(
selected
);
}
public
int
getSize() {
return
data.size();
}
public
Object getElementAt(
int
i) {
return
data.get(i);
}
public
void
addListDataListener(ListDataListener l) {
//rejestruje listenery zainteresowane zmianami modelu
}
public
void
removeListDataListener(ListDataListener l) {
//usuwa listenery zainteresowane zmianami modelu
}
}
Przygotował: Jacek Sroka
31
Wygląd i zachowanie
Standardowe podklasy LookAndFeel
●
javax.swing.plaf.metal.MetalLookAndFeel – domyślne
międzyplatformowe wygląd i zachowanie Javy; można go używać na każdej
platformie,
●
com.sun.java.swing.plaf.windows.WindowsLookAndFeel –
wygląd i zachowanie symulujące te znane z systemu Windows; obecnie
można ich używać tylko pod systemem Windows,
●
com.sun.java.swing.plaf.motif.MotifLookAndFeel – wygląd i
zachowanie CDE/Motif; domyślne na systemach firmy SUN; można go
używać na każdej platformie,
●
com.sun.java.swing.plaf.gtk.GTKLookAndFeel – wygląd i
zachowanie GTK+ (nie jest dostępny w wszystkich wersjach JRE).
●
wiele innych na http://www.javootoo.com/
Przygotował: Jacek Sroka
32
Przełączanie wyglądu i zachowania
●
w trakcie startu aplikacji
–
java -Dswing.defaultlaf=
com.sun.java.swing.plaf.gtk.GTKLookAndFeel
MyApp
●
jak nie doszło jeszcze do statycznej inicjalizacji żadnej klasy
Swinga
–
UIManager.setLookAndFeel(String)
●
w trakcie działania aplikacji
–
SwingUtilities.updateComponentTreeUI(Component)
●
dwie przydatne metody:
–
UIManager.getSystemLookAndFeelClassName()
–
UIManager.getCrossPlatformLookAndFeelClassName()
Przygotował: Jacek Sroka
33
Listwa górna i ramka okna
●
Niektóre wyglądy potrafią same rysować listwę górną i ramkę
okna, np. javax.swing.plaf.metal.MetalLookAndFeel
–
zazwyczaj jest dostarczana przez menadżera okien
–
JFrame.setDefaultLookAndFeelDecorated(true)
Przygotował: Jacek Sroka
34
Co dalej
●
Ćwiczenia z ważniaka
●
Połączenie GUI ze Scalą
●
Bardzo dobre przewodniki na
http://java.sun.com/docs/books/tutorial/
●
Projekt Matisse
http://www.netbeans.org/kb/trails/matisse.html