• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Java i JFrame, JPanel - podstawy

0 głosów
2,175 wizyt
pytanie zadane 22 listopada 2016 w Java przez itcloud Gaduła (3,380 p.)

Prosiłbym o pomoc w wytłumaczeniu, dlaczego to tak a nie inaczej działa. Zrobiłem sobie taki test:

package pl.test.dodge;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.*;

public class Dodge extends JPanel {
	

	public Dodge(){
		System.out.println("konstruktor Dodge()");
		setSize(new Dimension(500,400));
		setPreferredSize(new Dimension(500,400));
		setBackground(Color.black);
		
	}
	
	
	public void paint(Graphics g){
		//ta metoda jest caly czas wywolywana, nie musze jej wywolac
		System.out.println("metoda paint()");
		g.setColor(Color.BLACK);
		g.fillRect(0, 0, getWidth(), getHeight());
		System.out.println("opuszczam paint()");
	}
	
	
	public static void main(String[] args){
		
		System.out.println("tworze obiekt dodge w mainie");
		Dodge game = new Dodge();
		
		System.out.println("ciag dalszy maina");
		JFrame frame = new JFrame();
		frame.setTitle("Dodge the Rectangle");
		frame.add(game);   ///JAK TO ZAKOMENTUJE TO METODA PAINT NIE JEST WYWOLYWANA!
		frame.pack();
		frame.setResizable(false);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setLocationRelativeTo(null);
		frame.setVisible(true);
		
	}

}

1. Domyśliłem się, że metoda paint() jest automatycznie wywoływana przez jave w momencie, jak zaczynam rysować czyli korzystać z klasy JFrame? Ktoś może to rozwinąć? W tym moim przykładzie przeciążam tę metodę na podobnej zasadziej, jak przeciążamy (zalecane jest to) metodę toString() ?

2. Gdy zakomentuję frame.add(game) metoda paint() nie jest wywoływana - to dodanie "komponentu" (?) czy obiektu do ramki JFrame dopiero rozpoczyna proces rysowania?

3. Nie bardzo rozumiem, jak to się dzieje że: tworze klasę Dodge. Ok. Rozszerzam ją o klase JPanel. Dlaczego nie muszę rozszerzać o klasę JFrame? A dlaczego muszę rozszerzać o JPanel? Czy ma to związek z tym, że kolejność dziedziczenia jest taka:  Object -> Dodge (moja klasa) -> JFrame -> JPanel ? Prosiłbym o łopatologiczne wytłumaczenie bo się pogubiłem.

4. paint(Graphics g) - taki zapis jest możliwy, tak samo (na podobnej zasadzie) jakbym napisał paint(JFrame ramka) ? Czyli lokalnie przy wywołaniu funkcji paint tworzę obiekt g klasy Graphics i mogę dzięki temu z tego obiektu korzystać w tej metodzie? Korzystam z tutoriala. Normalnie napisałbym pewnie w metodzie:  Graphics g = new Graphics();

2 odpowiedzi

+2 głosów
odpowiedź 24 listopada 2016 przez Mateusz51 Nałogowiec (28,220 p.)
wybrane 24 listopada 2016 przez itcloud
 
Najlepsza
To idzie tak.

Metoda paint() jest to metoda typu callback. Tzn dajesz jej implementacjie ale nigdy ale to przenigdy nie powinieneś jej używać sam.Podsystem graficzny sam wywołuje tę metode gdy uzna że należy odrysować okno.(np przy zmianie rozmiaru okna) .Pobiera ona tak zwany kontekst graficzny graphics który pozwala Ci na rysowanie. Jak byś samemu wywoływał metode paint() musiał byś pobrać jakos ten kontekst. Co w wiekszosci przypadków kończy się katastrofą:) Jeśli chcesz wywołać metode paint() samemu musisz zrobić to pośrednio poprzez wywołanie metody repaint() na obiekcie( Pozwala to na zaimpementowanie animacji).

Dlaczego bez dodania Ci nie działa. Ponieważ JPanel jest tylko komponentem musisz dodać do do jakiegoś okna czyli u nas np JFrame. Bo maszyna wirtualna wykonuje metode paint() na oknie i paint jest wywoływany dalej w potomkach i potomkach potomków a nastepnie w potomkach........

Z racji że wiekszosc obiektów w swingu dziedziczy po contenerze, do każdego obiektu możesz dodać kolejne. (jeśli Cie interesuje sam mechanizm poczytaj o wzorcu projektowym kompozyt)

Jeśli chodzi o dziedziczenie. JPanel dziedziczy po JComponent który dziedziczy po Conteiner który dziedziczy po Component i dziedziczy po Obiekcie. JFrame po window który odrazy dzidzyczt po Conteiner.
Czyli są to troche różne dziedziczenia. Jeśli korzystasz z własnej metody paint polecam dziedziczyć po JComponent. APonieważ JPanel powstał aby grupować komponenty. Dziedziczysz po JComponent poto aby móc korzystać z wielu dobrodziejst i móc dodawać swoje komponenty do już istniejacych.
komentarz 24 listopada 2016 przez itcloud Gaduła (3,380 p.)
zrozumiałem co nieco tylko z tym paint() - ale nie rozumiem tam jednego, jeśli mogę przeciążyć metodę paint() (pisząc swoją) to i tak nie mogę jej wywoływać tak jak pisałeś?

Gdzie mogę o tym przeczytać co napisałęś apropo tego dziedziczenia itd. ?
1
komentarz 24 listopada 2016 przez Mateusz51 Nałogowiec (28,220 p.)
Dziedziczenie w dokumentacji Javy na samej górze masz drzewko diedziczenia https://docs.oracle.com/javase/8/docs/api/javax/swing/JPanel.html. Polecam się dobrze zapoznać z wygladem dokumentacji Javy bo to naprawde wiele ułatwia.

Z tym paint() to działa tak że jest to przepis dla podsystemu graficznego jak narysować twój komponent. Czyli tak jakbyś dał instrukcje do zrobienia czegoś. Nie ty decydujesz o rysowaniu, tylko podsystem graficzny właśnie. Jeśli chcesz zasugerować podsystemowi aby narysował twoj komponent musisz wywołać metode repaint(). Ale podsystem sam już zdecyduje kiedy to zrobi. (Tzn zrobi to ale nie musi odrazu)

Metoda paint jest wywoływana przez podsystem gdy np przesuwasz ekran, skalujesz okno, zamykasz i otwierasz. Czyli wtedy gdy coś się zmienia.
0 głosów
odpowiedź 22 listopada 2016 przez letni_deszczyk Obywatel (1,700 p.)
Rozszerzasz JPanel, ponieważ metodę paint wykonujesz na kontenerze (np. JPanel ale nie musi to być ten komponent), a nie na JFrame.

Kolejność dziedziczenia nie jest taka jak podałeś, Dodge dziedziczy przecież po JPanel, a więc nie może być przed nim.
komentarz 22 listopada 2016 przez itcloud Gaduła (3,380 p.)
Możesz rozwinąć to pierwsze zdanie? Gdzie widać, ze ją wykonuje na jPanel-u ?

Co do dziedziczenia: po prostu zastanawia mnie, czemu nie pisałem extends jFrame, tylko jPanel.
1
komentarz 22 listopada 2016 przez letni_deszczyk Obywatel (1,700 p.)
Paint jest metodą klasy JPanel po której dziedziczysz. Więc Twoja klasa automatycznie dziedziczy ją i dzięki temu możesz decydować jak ma wyglądać jej implementacja we własnej klasie.

 

Jeżeli chcesz rysować po panelu, to czemu miałbyś dziedziczyć po JFrame?
komentarz 23 listopada 2016 przez itcloud Gaduła (3,380 p.)
Ok, rozumiem, że podstawa to czytanie dokumentacji apropo klasy, z których się korzysta. Muszę wyrobic sobie ten nawyk.

Jeśli znalazłbyś chwilę i odpowiedział mi na moje pytania będę wdzięczny.

Podobne pytania

0 głosów
2 odpowiedzi 232 wizyt
pytanie zadane 5 grudnia 2016 w Java przez jaroslaw.slaby Początkujący (410 p.)
0 głosów
0 odpowiedzi 111 wizyt
pytanie zadane 6 grudnia 2016 w Programowanie przez jaroslaw.slaby Początkujący (410 p.)
+1 głos
1 odpowiedź 75 wizyt
pytanie zadane 10 kwietnia w Java przez coriver Nowicjusz (170 p.)

88,666 zapytań

137,277 odpowiedzi

306,617 komentarzy

58,867 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Sklep oferujący ćwiczenia JavaScript, PHP, rozmowy rekrutacyjne dla programistów i inne materiały

Oto dwie polecane książki warte uwagi. Pełną listę znajdziesz tutaj.

...