2D-Grafik Warum funktioniert dieser Code ? (GUI)

Hallo,

dies ist mein erster Post hier und ich muss sagen, dass ich noch ein ziemlicher Neuling in Sachen
Programmierung bin. Ich habe für die Uni zwar schon kleinere Priogramme geschrieben aber da
war nichts mit einem GUI bei und auch nichts, dass mich persönlich interessiert hat.

Daher habe ich mich selber einmal daran Versucht ein GUI zu basteln. Weit bin ich leider nicht
gekommen. Ich wollte gerne ein Hintergrundbild in ein Windowsfenster laden und bin dabei auf
folgenden Code gestoßen:

[JAVA=42]
import java.awt.*;
import java.awt.event.*;

public class test extends Canvas{

Image img = getToolkit().getImage("Pic1.jpg");

public void paint(Graphics g) {
g.drawImage(img,0,0,this);
System.out.println("Test");
}

public static void main(String[] args) {
Frame fr = new Frame ( "BildTest" );
fr.setSize(900, 900);

fr.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});

test test = new test();
fr.add(test);
fr.setVisible(true);
}
}
[/code]

Dieser funktioniert wunderbar ABER ... ich versteh nicht warum ...
Die Funktion paint (Zeile 49 - 52) bereitet mir Kopfzerbrechen ... sie wird nirgends aufgerufen,
jedoch funktioniert sie (siehe Testausgabe). Is das irgendetwas Java spezifisches ? Werden
Funktionen immer aufgerufen wenn sie vor der main Methode stehen ?

Und was ist wenn ich das ganze in mehrere Klassen aufteilen möchte ? also die Fenstererstellung
in eine Klasse, Canvas in eine Klasse etc. ... hab das mal versucht aber dann funktioniert der Code
nicht mehr ...

ich hoffe ihr könnt mich erleuchten ;-)
 
Werden
Funktionen immer aufgerufen wenn sie vor der main Methode stehen ?
nein! um Gottes willen!

Es ist ungefähr so das update irgendwo intern von Frame aufgerufen wird.
In der realität ist es etwas komplexer...
 
Zuletzt bearbeitet:
Danke erstmal für die Antwort ... aber ganz so hilft mir das noch nicht weiter ...
Was meinst du mit Update innerhalb von Frame ? Greift Frame auf die Funktion paint zu ?
und warum funktioniert der code dann nicht wenn man den in einzelne Klassen aufteilt ?
 
Swing merkt, wenn sich etwas an der Oberfläche ändert (z.B. wenn sie das erste mal angezeigt wird) und zeichnet dann die notwendigen Teile hierarchisch (d.h. Container rufen nicht nur das eigene paint, sondern auch die paint-Methoden ihrer Kinder auf) neu. Swing läuft in einem separaten Thread (EDT), also mehr oder weniger "parallel" zu deinem eigenen Programm.
 
Ich denke hier geht es gar nicht um die Grafik/GUI Programmierung... ich denke dir fehlt einfach das Basiswissen im Bereich Objektorientierter Programmierung..

Greift Frame auf die Funktion paint zu ?
was meinst du damit? Das sie die Funktion aufruft? Ja schon. (Wie genau oder was in Frame genau.. weiß ich nicht im Detail)
du fügst ja test (was ein Cavas ist) in Frame ein fr.add(test);

Also du fügst eine Zeichenfläche deinem Fenster hinzu... dein Fenster sorgt dann dafür das alles sauber gezeichnet wird... wie genau... tja da kannst du dir das JDK runter laden und dir den Source der Klassen ansehen... ;-) Oder du glaubst es einfach ...
 
Abgesehen davon wie die Komponenten ihre Paint-Aufrufe regeln, drängt sich mir da eine andere Frage auf: Hast du - Sonnenpriester - Objektorientierte Programmierung verstanden oder stehst du noch ganz am Anfang deiner Coder-Karriere?

Du machst hier nämlich mehrere Dinge in einer einzigen Klasse die gerade für einen blutigen Anfänger verwirrend wirken können:
  1. Du erstellst eine Klasse die als Hauptprogramm aufgerufen werden kann. (Mit der statischen Main-Methode)
  2. Du erstellst eine Klasse die von Canvas erbt und daher auch ein Canvas ist und überall eingesetzt werden kann wo auch ein Canvas hinpasst.
  3. In der Main-Methode erzeugst du eine neue Instanz der Klasse und übergibst diese einer Fenster-Klassen-Instanz Frame welche wiederum die Instanz-Methode paint zur gebotenen Stunde aufruft. (Z.B.: wenn du das Fenster verschiebst oder das Fenster zum ersten Mal aufpoppt.)

Du könntest das ganze prinzipiell auf 3 Klassen aufteilen:
  1. Das Hauptprogram mit der Main-Methode
  2. Eine Klasse die von Frame erbt und sich um den Listener für das Schließen kümmert und deine Klasse die von Canvas erbt enthält u. darstellt.
  3. Die Klasse die von Canvas erbt und dein Bild zeichnet.

Rein aus Interesse: Was studierst du und in welchem Semester bist du?
 
Also ... da das hier grad Schlag auf Schlag geht ... ein paar Erläuterungen zu meiner Person und dem Code oben ...

1)Der Code ist nicht von mir ich habe ihn aus dem Netz zum ausprobieren
2)Ich bin kein absoluter Anfänger aber mehr eben auch nicht ;-) ... ich weiß was Objektorientierte Programmierung ist aber manches (so wie oben) verwirrt mich dann doch manchmal.
3)Ich studiere digitale Medien und bin im Moment im fünften Semester (habe mit Java nur im 1. und 2. Semester zu tun gehabt, ist also auch wieder ne Weile her).
4)Ich habe den Code tatsächlich in 3 Teile aufgeteilt ... hoffe ihr könnt damit was anfangen (ist für mich auch schon n halbes Jahr her das ich daran gearbeitet habe):

Main.java
Java:
public class Main {
	
	public static void main(String[] args) {
		
		myCanvas c = new myCanvas();
		window MainWindow = new window(900,900,c);	//Das Fenster der Anwendung wir initialisiert
		MainWindow.setVisible(true);				//Das Fenster wird sichtbar gemacht
		
		
	}
}

window.java

Java:
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Canvas;
import java.awt.Frame;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

public class window extends Frame implements WindowListener, ActionListener {	
	
	public window(int width, int height,myCanvas c){
		
		setSize(width,height);						//Die Größe des Fensters wird gesetzt
		setTitle("OPOP - by Sonnenpriester v.alpha");	//Der Titel des Fensters wird gesetzt
		
		fillFrame(c);								//Das Fenster wird mit Objekten und allem gefüllt.			
		
		addWindowListener(this);					//Der WindowListener wir initialisiert
		
	}//Konstruktor
	
	public void fillFrame (myCanvas c){
		
		//hier kommt der Inhalt rein
		
		Panel top = new Panel();					//Ein neues Panel wird erstellt
		Panel center = new Panel();					//Ein neues Panel wird erstellt
		Button TEST = new Button("TEST");			//Ein neuer Button wir erstellt
		top.add(TEST);								//dem Panel "top" wird der Button "TEST" zugewiesen
		center.add(c);								//dem Panel "center" wird der Canvas "c" zugewiesen
		
		add(BorderLayout.CENTER, center);			//Dem Center Boarder Layout wird das Panel "center" zugewiesen
		add(BorderLayout.NORTH, top);				//Dem oberen Boarder Layout wird das Panel "top" zugewiesen
		
	}//fillFrame
	
	
	//Die Window Event Methoden die nötig sind
	//Sie müssen von Anfang an drinstehen !!
	
	public void windowClosing(WindowEvent e) {
		  System.exit(0);
		}

	public void windowActivated(WindowEvent arg0) {	}		
	public void windowClosed(WindowEvent arg0) { }
	public void windowDeactivated(WindowEvent arg0) { }
	public void windowDeiconified(WindowEvent arg0) { }
	public void windowIconified(WindowEvent arg0) { }
	public void windowOpened(WindowEvent arg0) { }
	public void actionPerformed(ActionEvent arg0) { }
																		
	private Canvas makeCanvas(){
		
		myCanvas CenterCanvas = new myCanvas();					//Eine neue Leinwand wird erstellt in die später ein Bild geladen wird 
		
	    return CenterCanvas;
	}
	

	
}//class window

myCanvas.java

Java:
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;



public class myCanvas extends Canvas {
	
	Image pic = getToolkit().getImage("Bilder/Pic1.jpg");
	
	public void paint(Graphics g) {
		g.drawImage(pic,0,0,this);
		System.out.println("paint");
	}
	
	public myCanvas(){
		this.setBackground(Color.yellow);
		System.out.println("Klasse myCanvas wird aufgerufen");
	}
	
}
 
Füge die Instanz von myCanvas direkt in den Centerbereich des Frames, statt es erst in ein Panel "center" (verwendet nämlich FlowLayout und ist daher auf die Größe der Komponente angewiesen) zu stecken. Das Canvas ist schon da nur sieht man es nicht, da es eine Größe von 0x0 hat.

Ansonsten noch ein Hinweis auf die Java Code Conventions: Klassennamen beginnen mit einem GroßBuchstaben, Methodennamen beginnen mit einem kleinBuchstaben.

Nach zwei Semestern Java/Programmieren ist es vielleicht auch noch ein bisschen früh mit einem GUI anzufangen - zumindest ohne eine passende Lektüre zu nutzen.
 

Zurück
Oben