Odczepimy się od technicznych rzeczy, a zajmiemy się artystycznymi. Być może nie wiecie, że "Swing" oferuje również komponent klasy "JPanel", który może posłużyć Wam do rysowania dowolnych kształtów geometrycznych na ekranie. Czy to linia, czy to kółko, okrąg, prostokąt, obrazek pobrany z pliku. Dzięki poznaniu metody "paintComponent", to wszystko staje się możliwe! Trzeba jednak obchodzić się z nią inaczej niż przy całej reszcie innych funkcji. Dalszy ciąg zostawiam w środku.

"PAINTCOMPONENT". CO W TYM MOŻE BYĆ DZIWNEGO?

Powyższa metoda kontroluje kiedy koniecznym jest ponowne przerysowanie całego panelu. Dorzucamy do niej wszystkie elementy, które mają być narysowane, aczkolwiek nie powinno się jej wywoływać samemu! Twórcy Javy sugerują taki manewr jako niezalecany, gdyż to system sam wywołuje tę metodę "pobudzając" do życia operacje niskopoziomowe, aby ponownie odświeżyć i przetworzyć obraz. Tak działa "paintComponent".

Powód bierze się z samego procesu rysowania. Obraz składający się z pojedynczych pikseli jest statyczny dopóki nie wymaga on ponownego przetworzenia pod wpływem jakiegoś zdarzenia. Na przykład rozciągnięcie okna jest sygnałem dla systemu, że obraz trzeba ponownie przerysować, gdyż współrzędne naszych figur geometrycznych mogą być zależne od szerokości okna. Albo gdy zminimalizujemy okno i przywrócimy je ponownie. To są tylko takie przykłady bo ja nie znam wszystkich przypadków jakie są dla systemu argumentem do ponownego wywołania metody "paintComponent".

Funkcja domyślnie rysuje w taki sposób, jakby to była jedna klatka. Jakby obecną chwilę "zatrzymał w czasie" i rozrysował wszystko to, co zostało zawarte w omawianej metodzie. Możemy jednak sprawić, żeby ponownie przerysował cały panel korzystając z innej już metody do tego przeznaczonej, "repaint". Nie przyjmuje żadnych argumentów i pozwala "nakazać" funkcji "paintComponent" narysować wszystko jeszcze raz.

Przy obiektach wprawionych w ruch może to powodować problem zachowania poprzedniej "treści" rysunku. Nie myślcie, że funkcja automatycznie czyści zawartość poprzedniej klatki, aby zrobić miejsce dla obecnych wyników. Bez zadbania o czyszczenie ekranu, przemieszczające się obiekty zaczną się "rozjeżdżać" więc konieczna będzie jeszcze jedna metoda czyszcząca albo przykrywająca całą zawartość (wywołanie "super.paintComponent" na samym początku rozwiązuje ten problem).

Animacja "Swing" po działaniu "paintComponent" bez czyszczenia klatki

To jest "efekt uboczny" animowania obiektu bez czyszczenia klatki. Translacja okręgu przy inkrementacji osi X i Y co klatkę.

KOD ŹRÓDŁOWY Z METODĄ "PAINTCOMPONENT"

Oszczędzimy sobie na razie poznawanie metod jak narysować wszystkie dostępne figury. Skupimy się najpierw na samej istocie ujrzenia czegokolwiek na panelu, który zostanie "przytwierdzony" do ramki. Oto kod:

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

public class SwingWindow extends JFrame
{
	private SwingPanel panel;

	public SwingWindow()
	{
		createInstances();
		addToFrame();
		configure();
	}

	private void createInstances()
	{
		panel = new SwingPanel();
	}

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

		pane.add(BorderLayout.CENTER, panel);
	}

	private void configure()
	{
		setTitle("Rysowanie po panelu JPanel");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
		setResizable(false);
		setSize(800, 600);
		setLocationRelativeTo(null);
	}
}
  • KLASA "SwingPanel"
import java.awt.*;
import javax.swing.*;

public class SwingPanel extends JPanel
{
	@Override
	protected void paintComponent(Graphics g)
	{
		super.paintComponent(g);
		g.setColor(Color.BLUE);
		g.drawOval(64, 64, 320, 320);
		System.out.println("Rysowanie zakończone.");
	}
}

Oddzieliłem jeden komponent od drugiego, aby pomóc Wam skupić się na rzeczach istotnych. Przyjrzyjcie się klasie "SwingPanel". Korzysta ona z innego komponentu, którego jeszcze nie omówiłem, "JPanel". On udostępnia rysowanie dowolnych figur geometrycznych oraz obrazków pobieranych z podanej ścieżki dostępu. Szczegóły zostawimy sobie na odrębny artykuł.

Metoda "paintComponent" musi być nadpisana w celu "nagięcia" jej do swoich potrzeb, zatem stosujemy adnotację "@Override". Modyfikator "protected" nie jest tu koniecznie wymagany, tak mi jedynie zasugerował IDE. Ten modyfikator jest bardzo rzadko wykorzystywany i temat na razie pominiemy. Pierwszym wywołaniem powinna być metoda bazowa "paintComponent". Ona pozwala zastąpić metodę, która musiałaby "posprzątać" po tej poprzedniej klatce o której napisałem powyżej.

Metody rysujące po panelu udostępnia nam klasa "Graphics". W powyższym przykładzie ustawiamy kolor rysowania na niebieski ("Color.BLUE"). Klasa "Color" posiada statyczne metody i zmienne umożliwiające wykorzystywanie gotowych kolorów lub tworzenie własnych na zasadzie palety RGB. W "Swing", rysowanie według odpowiedniego koloru polega na wywołaniu metody ustawiającej kolor, a dopiero wtedy idą funkcje rysujące.

Dalej mamy "drawOval". To jest rysowanie samego okręgu (nie koła, zatem rysuje sam obwód). Za parametry podajemy współrzędne X i Y, a następnie szerokość i wysokość. Po uruchomieniu programu, "paintComponent" narysuje nam niebieski okrąg. Nic specjalnego jednak trzeba zacząć od samej struktury, aby Was nie przytłoczyć ilością materiału i metod przeznaczonych do rysowania figur.


Kończę. Traktujcie to jako "dotknięcie" tego tematu bo jest on bardziej rozbudowany. Jeśli zaciekawiłem tematem, to czytajcie od razu dalszy ciąg!

PODOBNE ARTYKUŁY