I to już będzie ostatnia część na dzisiejszy dzień, zatem powracamy do tego samego pytania: "jak zaprogramować zdarzenie do przycisku tak, aby po jego naciśnięciu coś się wydarzyło?". Dłuży się to niemiłosiernie, natomiast trzeba aż tak wielu wyjaśnień, aby korzystać z tego świadomie i rozsądnie. Znamy już klasy wewnętrzne, ich budowę, dowiemy się teraz jak mogą nam pomóc w rozwiązaniu problemu. Samo tworzenie zdarzeń w Javie określane jest jako "obsługa zdarzeń" tak jak to mieliśmy z wyjątkami, co nie? Przechodzimy do tematu.

OBSŁUGA ZDARZEŃ PO STAROŚWIECKU

Pierwszym z dwóch rozwiązań będzie umieszczenie klasy wewnętrznej posiadającej funkcję, która z kolei będzie wywoływana po naciśnięciu przycisku. Tylko jest mały niuans: tutaj cały czas nawijam o klasach wewnętrznych, a ostatni raz gdy było o bibliotece Swing, to nie wspomniałem od czego się to w ogóle zaczyna! Moi drodzy, od zaimplementowania interfejsu "ActionListener" do danej klasy.

Gdy mamy do czynienia tylko z jednym przyciskiem, to mogliśmy sobie darować to całe rozgrzebywanie tematu klas wewnętrznych. Domyślam się jednak, że 99% Waszych programów będzie wymagało więcej niż jednego przycisku. CHWILA! Przecież w Javie możemy dorzucić tyle interfejsów ile chcemy! Zgadza się, ale nie w tym tkwi problem. Problem polega na tym, że interfejs o tej samej nazwie, może obsługiwać TYLKO JEDEN przycisk na interfejs a to z kolei oznacza, że możemy "podpiąć" tylko jeden przycisk na klasę. O to tutaj chodzi!!!

PRZYKŁAD Z DWOMA PRZYCISKAMI

W porządku, jeśli nie pokapowaliście do końca, to może spróbujcie na to spojrzeć z programistycznego punktu widzenia. Obsługa zdarzeń dwóch przycisków na jednej "ramce" czyli oknie i przedstawienie implementacji interfejsów we właściwe miejsca. Wyjaśnienia wszystkich nowości zostawiam poniżej:

  • KLASA "Main"
public class Main
{
	public static void main(String[] args)
	{
		new SwingButton();
	}
}
  • KLASA "SwingWindow"
import java.awt.*;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class SwingButton extends JFrame implements ActionListener
{
	private JButton buttonA, buttonB;

	public SwingButton()
	{
		createInstances();
		addButtonListeners();
		addToFrame();
		configure();
	}

	private void createInstances()
	{
		buttonA = new JButton("Kliknij mnie!");
		buttonB = new JButton("Najpierw mnie!");
	}

	private void addButtonListeners()
	{
		buttonA.addActionListener(this);
		buttonB.addActionListener(new ButtonBListener());
	}

	private void addToFrame()
	{
		Container pane = getContentPane();

		pane.add(BorderLayout.NORTH, buttonA);
		pane.add(BorderLayout.SOUTH, buttonB);
	}

	private void configure()
	{
		setTitle("Obsługa zdarzeń przycisków w Swing");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
		setResizable(false);
		setSize(512, 256);
		setLocationRelativeTo(null);
	}

	@Override
	public void actionPerformed(ActionEvent e)
	{
		System.out.println("PRZYCISK A ZOSTAŁ KLIKNIĘTY!");
	}

	private class ButtonBListener implements ActionListener
	{
		@Override
		public void actionPerformed(ActionEvent e)
		{
			System.out.println("PRZYCISK B ZOSTAŁ KLIKNIĘTY!");
		}
	}
}

Do całej operacji potrzeba szeregu importów widocznych na górze, których nie ma sensu maglować i tutaj. Obsługa zdarzeń sama w sobie nie wymaga aż tak wiele. Jak powiedziałem, interfejs "ActionListener", który żąda zdefiniowania metody "actionPerformed", a w środku niej podajecie instrukcje. A jak połączyć jedno z drugim? Teraz mogę Wam zdradzić. Za pomocą metody "addActionListener" poprzez instancję przycisku. Za parametr podajecie klasę implementującą wyżej wymieniony interfejs albo tworzycie nową, taka sytuacja również została przedstawiona powyżej.

Jeszcze jeden znak zapytania może powstać u Was patrząc na metodę "addToFrame". Aby uniknąć ciągłego odwoływania się do metody "add" poprzez "getContentPane" (tak, to jest konieczne w przypadku klasy "JFrame") można zostawić sobie zmienną lokalną przechowującą referencję typu "Container". Dalej, co to "BorderLayout.NORTH" i "BorderLayout.SOUTH"? To są dwa z kilku dostępnych obszarów układu "BorderLayout", których w tym przypadku jest pięć (więcej szczegółów będzie w odrębnym artykule).


Tak się rozwiązywało problem przed wprowadzeniem Javy 8. Obsługa zdarzeń wymagała niekonwencjonalnego podejścia. A jak wygląda to teraz? Przekonacie się jutro.

PODOBNE ARTYKUŁY