- Kontrolki są rozmieszczane przez LayoutManagera,
którym domyślnie jest BorderLayout działajacy, jak w poprzednim
przykładzie. Możemy ustawić innego LayoutManagera, oferującego inny
rodzaj funkcjonalności i zapewniający inne rozmieszczenie naszych
kontrolek. Poniższą linię należy dodać przed linijkami dodającymi
kontrolki:
frame.setLayout(new FlowLayout());
- Po przetestowaniu FlowLayout sprawdź jak zadziała
GridLayout:
frame.setLayout(new GridLayout(2,2));
- Bardziej zaawansowane projekty interfejsu można realizować
przy wykorzystaniu klasy JPanel, będącej swego rodzaju "workiem" na
kontrolki, reprezentującej podokno, które może mieć swego własnego
LayoutManagera. Możemy np. ustawić BorderLayout dla okna głównego:
frame.setLayout(new BorderLayout());
- Teraz stwórzmy panel:
JPanel panel = new JPanel();
- ...który będzie korzystał z GridLayout:
panel.setLayout(new GridLayout(3,3));
- Dodajmy tam 9 przycisków:
for(int i = 0; i < 9; ++i)
panel.add(new JButton(""+(i+1)));
- Panel, oraz resztę kontrolek dodamy do głównego okna:
frame.add(panel, BorderLayout.CENTER);
frame.add(label, BorderLayout.SOUTH);
frame.add(tekst, BorderLayout.NORTH);
frame.add(ok, BorderLayout.EAST);
- Jeśli wywołanie metody setSize wymienimy na pack, rozmiar okna
dostosuje się do zawartości (robimy to oczywiście dopiero gdy w oknie
jest już jakaś zawartość):
frame.pack();
- Uruchom i przetestuj.
- Teraz sprawmy, aby nasze przyciski zaczęły działać. W tym
celu należy dodać "Listenera". Jest to obiekt o określonym interfejsie,
zawierajacy metodę implementującą żądaną funkcjonalność. Obiekt
dowiazujemy np. do przycisku. W momencie gdy wykonana jest akcja
(użytkownik naciśnie przycisk) wykona się nasza funkcja. Napiszmy
prostego Listenera (ale najpierw dodaj import pakietu java.awt.event) - na razie jako zwyczajną klasę zewnętrzną:
class MojaAkcja implements ActionListener {
public void actionPerformed(ActionEvent ev) {
System.out.println("naciśnięto OK");
}
}
- Teraz możemy powiązać stworzonego Listenera z przyciskiem "OK" (znów w funkcji main):
ok.addActionListener(new MojaAkcja());
- Uruchom i przetestuj.
- Możemy też sprawić, aby przycisk powodował zmianę tekstu w którejś z kontrolek okna, wymieniając System.out.println np. na:
tekst.setText("hello, " + tekst.getText());
- Problemem
może być dostanie się do zmiennej tekst, która jest niewidoczna z
poziomu funkcji actionPerformed - można wydostać ją na kilka sposobów,
np. przekazując jako parametr kontruktora klasy MojaAkcja:
private JTextField tekst;
public MojaAkcja(JTextField tekst) {
this.tekst = tekst;
}
- ...i modyfikując kod dowiązujący Listenera do przycisku:
ok.addActionListener(new MojaAkcja(tekst));
- Innym
rozwiązaniem jest uczynienie klasy MojaAkcja klasą wewnętrzną - jeśli
umieścimy jej definicję wewnątrz metody main, będzie ona miała dostęp
do jej zmiennych lokalnych (pod warunkiem że zostana zadeklarowane jako
finalne) - nie będzie wówczas potrzebny żaden dodatkowy parametr:
final JTextField tekst = new JTextField("world");
class MojaAkcja implements ActionListener {
public void actionPerformed(ActionEvent ev) {
tekst.setText("hello, " + tekst.getText());
}
}
ok.addActionListener(new MojaAkcja());
- Jeszcze
lepszym rozwiązaniem będzie uczynienie jej klasą anonimową - podstawowa
modyfikacja to usunięcie nazwy. Klasę anonimową definiujemy
bezpośrednio w miejscu jej użycia (czyli tworzenia obiektu):
ok.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent ev) {
tekst.setText("hello, " + tekst.getText());
} // koniec actionPerformed
} // koniec definicji klasy
); // nawias zamykający ok.addActionListener();