1. Treści programowe:
Programowanie komponentów
graficznych z pakietu Swing, ranka aplikacji, kontenery, szablon
rozmieszczenia, programowanie zdarzeniowe, interfejs ActionListener.
2. Cel zajęć:
Opanowanie umiejętności
programowania aplikacji z graficznym interfejsem użytkownika oraz obsługi
zdarzeń związanych z akcją przycisków. Praktyczne wykorzystanie interfejsów
oraz metod interfejsu ActionListener.
Świadome rozmieszczanie obiektów w interfejsie użytkownika.
3. Pomoce
dydaktyczne:
Programowanie
aplikacji z wykorzystaniem typowych elementów występujących w większości dzisiejszych
programów, jak przyciski, listy, rozwijane listy, pola tekstowe, menu, paski
narzędziowe, itd. odbywa się poprzez gotowe zbiory klas. Można je importować do
swojego programu i używać tak jakby były częścią naszego projektu. Obecnie
najnowsza biblioteka komponentów aplikacji to JavaFX. Ponieważ najważniejszym
celem zajęć jest umiejętność posługiwania się mechanizmami języka java dlatego
wybrano pakiet Swing, który jest poprzednikiem javaFX po to aby łatwiej i
szybciej wykorzystać poznane mechanizmy bez wchodzenia w szczegóły
programowania nowoczesnych interfejsów użytkownika. Chodzi o to, aby znając
najważniejsze elementy języka java, każdy potrafił sam wykorzystywać nowe
biblioteki i rozwiązania tam zawarte. Pakiet JavaFX wymaga więcej czasu na
zapoznanie się z prawidłową budową aplikacji wykorzystującą zewnętrze pliki
projektu z komponentami opisanymi w języku XML. Wykorzystując pakiet swing
szybciej będzie można pokazać, np. tryb graficzny, programowanie wielowątkowe
itd. Docelowo zachęcam każdego programistę do samodzielnej nauki JavaFX.
Java SWING
Przykład
ramki aplikacji o szerokości 500 px oraz wysokość 400 px. Lewy górny róg
oddalony jest o 200 px od lewej krawędzi ekranu oraz o 100 px od górnej
krawędzi. Funkcja setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) sprawia, iż
przycisk wyłączający okno ramki wyłącza całą aplikację. Argument
true metody setVisible powoduję, że okno jest widoczne.

import javax.swing.*;
public class Program1 extends
JFrame {
Program1(){
super("Moja pierwsza aplikacja");
setBounds(200,100,500,400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
public static
void main(String[] args) {
new Program1();
}
}
Do
ramki aplikacji dodano panel, który jest kontenerem, do którego dodano dwa
przyciski. Domyślnie przyciski wyświetlane są na środku panelu, ponieważ
bezargumentowy konstruktor JPanel tworzy siatkę rozmieszczenia FlowLayout
(latające obiekty).

import javax.swing.*;
public class Program1 extends JFrame {
Program1(){
super("Moja pierwsza aplikacja");
setBounds(200,100,500,400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
JButton przycisk1 = new JButton("Przycisk 1");
JButton przycisk2 = new JButton("Przycisk 2");
panel.add(przycisk1);
panel.add(przycisk2);
setContentPane(panel);
setVisible(true);
}
public static void main(String[] args) {
new Program1();
}
}
Aby możliwe było rozmieszczenie
przycisków w dowolnie wskazanym miejscu panelu należy w konstruktorze JPanel
wstawić wartość null. Sprawi to, iż żadna siatka nie będzie utworzona oraz
metoda setBounds ustawi obiekt we wskazanym miejscu z określoną szerokością i
wysokością.

import javax.swing.*;
public class Program1 extends JFrame {
Program1(){
super("Moja pierwsza aplikacja");
setBounds(200,100,500,400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(null);
JButton przycisk1 = new JButton("Przycisk 1");
JButton przycisk2 = new JButton("Przycisk 2");
przycisk1.setBounds(100, 230, 100,25);
przycisk2.setBounds(300, 230, 100,25);
panel.add(przycisk1);
panel.add(przycisk2);
setContentPane(panel);
setVisible(true);
}
public static void main(String[] args) {
new Program1();
}
}
Dodanie dwóch obiektów: Pola
tekstowego (do edycji tekstu) JTextField oraz etykiety JLabel
JLabel labelEtykeita = new JLabel("Tekst etykiety");
labelEtykeita.setBounds(100,70,300,25);
panel.add(labelEtykeita);
JTextField textFieldTekst = new JTextField("Tekst w polu tekstowym ");
textFieldTekst.setBounds(100, 100, 300,25);
panel.add(textFieldTekst);
Interfejs w języku Java to zestaw metod
bez ich implementacji, czyli bez kodu definiującego zachowanie metody. Właściwa
implementacja metod tego interfejsu znajduje się w klasie
implementującej dany interfejs. W tej instrukcji będziemy używać
interfejsy biblioteczne, nie będziemy na razie deklarować własnych interfejsów.
Tym zajmiemy się w późniejszym czasie.
Przykład dodania interfejsu do
klasy:
class NazwaKlasy implements NazwaInterfejsu
{ ......
Metoda
abstrakcyjna interfejsu ActionListener:
public
void actionPerformed(ActionEvent e){
Object
src = e.getSource();
if (src ==
obiekt) // sprawdzanie, który obiekt wygenerował zdarzenie akcji
// instrukcje
....
}
Poniższy przykład
przedstawia obsługę zdarzenia związanego z naciśnięciem przycisków. Do obsługi
tego zdarzenia niezbędny jest interfejs ActionListener oraz metoda abstrakcyjna
tego interfejsu o nazwie actionPerformed.

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Program1 extends JFrame implements ActionListener {
JButton przycisk1, przycisk2; // Aby można było używać
//obiektów poza konstruktorem
//zostały przniesione i ustawione jako globalneJTextField textFieldTekst;
JLabel labelEtykeita;
Program1(){
super("Moja pierwsza aplikacja");
setBounds(200,100,500,400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(null);
przycisk1 = new JButton("Przycisk 1");
przycisk2 = new JButton("Przycisk 2");
przycisk1.setBounds(100, 230, 100,25);
przycisk2.setBounds(300, 230, 100,25);
labelEtykeita = new JLabel("Tekst etykiety");
labelEtykeita.setBounds(100,70,300,25);
panel.add(labelEtykeita);
textFieldTekst = new JTextField("Tekst w polu tekst… ");
textFieldTekst.setBounds(100, 100, 300,25);
panel.add(textFieldTekst);
panel.add(przycisk1);
panel.add(przycisk2);
przycisk1.addActionListener(this); // metoda powoduje, że
//przycisk1 nasłuchuje na zdarzenie naciśnięciaprzycisk2.addActionListener(this); // metoda powoduje, że
//przycisk2 nasłuchuje na zdarzenie naciśniecia setContentPane(panel);
setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
Object object=e.getSource();
if(object==przycisk1){
String tekst = textFieldTekst.getText();
labelEtykeita.setText(tekst);
}else if(object==przycisk2){
System.exit(0);
}
} public static void main(String[] args) {
new Program1();
}
}
Poniżej przedstawiano aplikację
działającą dokładnie tak jak wcześniejsza. Różnica polega na implementacji klas
interfejsu. Do każdego przycisku dodajemy obsługę zdarzeń tworząc instancję
klasy interfejsu (działa od wersji java 8). W tworzeniu takiej konstrukcji
pomaga nam InteliJ Idea, gdzie po wpisaniu pierwszej litery proponowane są na
propozycji całej konstrukcji.
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Program1 extends JFrame {
JButton przycisk1, przycisk2;
JTextField textFieldTekst;
JLabel labelEtykeita;
Program1(){
super("Moja pierwsza aplikacja");
setBounds(200,100,500,400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(null);
przycisk1 = new JButton("Przycisk 1");
przycisk1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String tekst = textFieldTekst.getText();
labelEtykeita.setText(tekst);
}
});
przycisk2 = new JButton("Przycisk 2");
przycisk2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
przycisk1.setBounds(100, 230, 100,25);
przycisk2.setBounds(300, 230, 100,25);
labelEtykeita = new JLabel("Tekst etykiety");
labelEtykeita.setBounds(100,70,300,25);
panel.add(labelEtykeita);
textFieldTekst = new JTextField("Tekst w polu tekst… ");
textFieldTekst.setBounds(100, 100, 300,25);
panel.add(textFieldTekst);
panel.add(przycisk1);
panel.add(przycisk2);
setContentPane(panel);
setVisible(true);
}
public static void main(String[] args) {
new Program1();
}
}
Wybrane metody:
getText
() – pobiera tekst z
obiektu tekstowego,
setText(String) – wstawia tekst do obiektu
tekstowego.
Konwersja
danych z tekstu do wartości całkowitej:
int liczba = Integer.parseInt(wartoscString);
4. Zadania
Zadanie 1
Napisz
aplikację dodającą liczby całkowite, jak na rysunku poniżej:

·
przycisk Wyczyść - usuwa zawartość
wszystkich pól tekstowych,
·
przycisk Dodaj - dodaje wartości pobrane z pierwszego i drugiego pola tekstowego
oraz ich sumę wyświetla w polu trzecim.
Zadanie 2
Napisz
program według własnego pomysłu, w którym umieść wymienione w materiałach
obiekty oraz wykorzystaj programowanie zdarzeniowe.