Tym razem postawiłem napisać o czymś, czym się aktualnie zajmuję na uczelni czyli programowaniem w Javie, a konkretniej programowanie interfejsu graficznego w Swingu. Java Swing jest w pełni obiektową (jak sam język) biblioteką graficzną służącą do majstrowania okienkowego GUI (podobnie jak QT, czy też Windows Forms). Korzystanie z tej biblioteki jest bardzo proste, niestety ma ona jedną podstawową wadę (oprócz bycia w Javie) – domyślnie okienko posiada własny style, więc nie wykorzystuje systemowego, dlatego może się wyróżniać.
Tworzenie okienek w Swingu jest bardzo proste, przykładowo wyświetlenie pustego okienka wygląda następująco:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| import javax.swing.SwingUtilities;
import javax.swing.JFrame;
public class Okienko
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
JFrame f = new JFrame();
f.setTitle("Hello World!");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(290, 250);
f.setVisible(true);
}
});
}
} |
import javax.swing.SwingUtilities;
import javax.swing.JFrame;
public class Okienko
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
JFrame f = new JFrame();
f.setTitle("Hello World!");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(290, 250);
f.setVisible(true);
}
});
}
}
Ten krótki kod tworzy prostą formatkę JFrame, a następnie ustawia jej tytuł, rozmiar, akcje zamnięcia i na końcu pokazuje okienko. Wszystko to jest wykonywane w funkcji run() anonimowej klasy wewnętrznej po interfejsie Runnable (swoją drogą najpiękniejszy mechanizm w Javie :)), która działa w osobnym wątku biblioteki Swing. Jak widać jest to bardzo proste.
Co jednak gdy chcemy stworzyć coś bardziej wyszukanego? Wtedy najlepiej rozszerzyć (odziedziczyć) klasę JFrame. Mając własną klasę o wiele łatwiej wszystkim zarządzać wszystkimi komponentami, które znajdują się na formatce. Poniższy kod tworzy formatkę i wyświetla na niej przycisk i pole tekstowe:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| import java.awt.FlowLayout;
import javax.swing.*;
public class Okienko extends JFrame
{
private JButton bPisz = new JButton("Pisz");
private JTextArea textArea = new JTextArea(10, 20);
public Okienko()
{
setTitle("Hello World!");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(290, 250);
setLayout(new FlowLayout());
add(new JScrollPane(textArea));
add(bPisz);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new Okienko().setVisible(true);
}
});
}
} |
import java.awt.FlowLayout;
import javax.swing.*;
public class Okienko extends JFrame
{
private JButton bPisz = new JButton("Pisz");
private JTextArea textArea = new JTextArea(10, 20);
public Okienko()
{
setTitle("Hello World!");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(290, 250);
setLayout(new FlowLayout());
add(new JScrollPane(textArea));
add(bPisz);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new Okienko().setVisible(true);
}
});
}
}
Powyższy kod jest już troszkę dłuższy, a jego zadanie polega na wyświetleniu na formatce przycisku oraz pola tekstowego. Pojawiły się tutaj dodatkowe komponenty takie jak: JButton, JTextArea, JScrollPane oraz funkcja setLayout(). Dwa pierwsze są oczywiste, bo jest to wspomniany przycisk i pole tekstowe, natomiast JScrollPane jest dodatkowym komponentem dodającym do JTextArea paski przesuwania (to wszystko przez proste opakowanie go). Funkcja setLayout() ustawia sposób rozmieszczenia kontrolek. Domyślnym układem jest BorderLayout, który kontrolki układa jedna na drugiej, natomiast FlowLayout ustawia je w taki sposób aby wszystkie były widoczne (po szczegóły zapraszam do dokumentacji :)).
No cóż mamy przycisk, ale teraz co zrobić, aby po jego naciśnięciu coś się stało. Obsługa akcji na kontrolkach opiera się na zdarzeniach, czyli w przypadku naciśnięcia przycisku wywoływana jest odpowiednia funkcja, która to zdarzenie potrafi obsłużyć. W takim razie jak obsłużyć akcję wciśnięcia przycisku? W tym celu należy dodać do przycisku odbiorcę zdarzenia za pomocą funkcji addActionListener(). Funkcja ta przyjmuje referencję do interfejsu ActionListener, z którego należy zaimplementować funkcję actionPerformed(). Właśnie ta funkcja zostanie wywołana w momencie wystąpienia zdarzenia.
Wynikowy kod:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
| import java.awt.FlowLayout;
import javax.swing.*;
import java.awt.event.*;
public class Okienko extends JFrame
{
private JButton bPisz = new JButton("Pisz");
private JTextArea textArea = new JTextArea(10, 20);
public Okienko()
{
setTitle("Hello World!");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(290, 250);
bPisz.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
textArea.append("Hello World ");
}
});
setLayout(new FlowLayout());
add(new JScrollPane(textArea));
add(bPisz);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new Okienko().setVisible(true);
}
});
}
} |
import java.awt.FlowLayout;
import javax.swing.*;
import java.awt.event.*;
public class Okienko extends JFrame
{
private JButton bPisz = new JButton("Pisz");
private JTextArea textArea = new JTextArea(10, 20);
public Okienko()
{
setTitle("Hello World!");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(290, 250);
bPisz.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
textArea.append("Hello World ");
}
});
setLayout(new FlowLayout());
add(new JScrollPane(textArea));
add(bPisz);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new Okienko().setVisible(true);
}
});
}
}