# Bewegtes zeichnen in Swing



## Psypsy (15. Jun 2009)

Moin,

ich versuche mich neuerdings mal an der Grafikprogrammierung und bleibe auch gleich am Anfang schon hängen.

Ich habe google und eure Sufu benutz nur nichts gefunden oder die falschen Suchwörter eingegeben.

Also mein problem ist ich versuche in einer Javaanwendung eine einfache gezeichnete sache ( Strich, Kreis, Rechteck, usw.) bewegen zulassen und das direkt nach Programmstart.
Ich habe bei euch und in einigen Tutorials gefunden wie man das macht wenn man auf ein Event reagiert, aber ich möchte erstmal noch eine Stuffe davor einiges machen.

Mein Grundgerüst:

```
import java.awt.*;
import javax.swing.*;

public class Fenster extends JFrame {

	public Fenster() {
		setTitle("Titel");
		setBackground(Color.LIGHT_GRAY);
		add(new Leinwand());
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

	public static void main(String args[]) {
		Fenster hauptfenster = new Fenster();
		hauptfenster.setSize(800, 600);
		hauptfenster.setLocation(200, 100);
		hauptfenster.setVisible(true);

	}

	private class Leinwand extends JPanel {
		public void paintComponent(Graphics g) {
			super.paintComponent(g);
			Graphics2D g2d = (Graphics2D) g;

		}
	}
}
```

Wenn ich jetzt in paintComponent zeichne funktioniert das, daß ist ja auch kein Problem
aber ich möchte das ganze ja bewegen.

Zeitverzögerungen bekomme ich mit "Thread.sleep(xxx)" im try/catch-block.
Ich weiß auch das ich das zeichnen in einen neuen Thread starten muss damit sich das Hauptfenster erstmal aufbauen kann und ich dann darauf zeichne.
Aber das bekomme ich irgendwie nicht hin.

???:LKönnt Ihr mir bitte helfen da mal vom Schlauch runterzukommen???:L

Mit freundlichen Grüßen

PsyPsy


----------



## Schandro (15. Jun 2009)

Beispielcode:

```
import java.awt.Color;
import java.awt.Graphics;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class XXX{

    public static void main(String[] args){
        new XXX();}


    private JFrame window = new JFrame();
    private int cnt; // wird zur Kommunikation ziwschen dem animationThread und paintComponent benutzt

    public XXX(){
        window.setBounds(100,100,400,200);
        window.add(panel);

        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                window.setVisible(true);
            }
        });

        Thread animationThread = new Thread(new Runnable(){
            public void run(){
                while(cnt < 300){
                    ++cnt;
                    panel.repaint();

                    try{
                        Thread.sleep(10); // hier im Beispiel wird jede 10 Millisekudnen neugezeichnet.
                    }catch(InterruptedException e){
                        e.printStackTrace();
                    }
                }
            }
        });
        animationThread.start();
    }


    JPanel panel = new JPanel(){
        public void paintComponent(Graphics g){
            super.paintComponent(g);

            g.setColor(Color.BLACK);
            g.fillRect(cnt,50,50,50);
        }
    };

}
```
Das man innerhalb der paintComponent-Methode auf keinen Fall Thread.sleep aufrufen darf, hast du schonmal richtig erkannt. Die Kommunikation zwischen den Thread und der paintComponent-Methode läuft über Membervariablen (in diesem Fall über das int cnt, du kannst aber beliebig viele Membervariablen beliebigen Types dafür einsetzen)

Tipp: Um den Code besser rauszukopieren, gibts seit heute Mittag ne neue Funktion hier im Forum: Einfach auf das Symbol rechts neben "Java Code: " überhalb des eigentlichen Codes klicken. Dann einfach Strg+a, Strg+C^^


----------



## -MacNuke- (16. Jun 2009)

Tipp: SwingTimer nehmen, statt einem Thread.  Macht die Sache besser kontrollierbar und ist auch performanter.


----------



## Schandro (16. Jun 2009)

> Tipp: SwingTimer nehmen, statt einem Thread.  Macht die Sache besser kontrollierbar und ist auch performanter.


Warum besser kontrollierbar? Weil ich auf den Timer Methoden aufrufen muss um die Wiederholungsfrequenz zu verändern oder den Timer zu starten/stoppen? Das ist nur ne andere "Syntax", ändert aber nix an der Kontrolle die man darüber hat...
Außerdem ist der Thread nebenläufig zu dem Zeichenprozess, deswegen ist die Rate in der cnt verändert wird immer ca. 10 ms, auch wenn paintComponent länger als 10 ms zum berechnen brauchen würde.
Egal, jeden das seine.


----------



## Guybrush Threepwood (16. Jun 2009)

-MacNuke- hat gesagt.:


> Tipp: SwingTimer nehmen, statt einem Thread.  Macht die Sache besser kontrollierbar und ist auch performanter.



Ist das wirklich performanter? Ich habe bislang für Animationen immer einen normalen Thread genommen  und über allerlei Tricksereine (z. B. setClip()) versucht, die Performanz zu steigern. Gibt es dazu Quellen, wo das näher beschrieben ist?


----------



## -MacNuke- (16. Jun 2009)

Schandro hat gesagt.:


> Warum besser kontrollierbar? Weil ich auf den Timer Methoden aufrufen muss um die Wiederholungsfrequenz zu verändern oder den Timer zu starten/stoppen? Das ist nur ne andere "Syntax", ändert aber nix an der Kontrolle die man darüber hat...



Nunja. Thread-Handling ist allgemein etwas aufwändiger als mal fix start/stop aufzurufen. Zumal du bei einem Thread nicht mal sicher gehen kannst, dass stop auch wirklich stop ist.



Schandro hat gesagt.:


> Außerdem ist der Thread nebenläufig zu dem Zeichenprozess, deswegen ist die Rate in der cnt verändert wird immer ca. 10 ms, auch wenn paintComponent länger als 10 ms zum berechnen brauchen würde.
> Egal, jeden das seine.



"repaint" ist sowieso kein NeuzeichnenBEFEHL sondern nur eine BITTE. Damit legst du nur ein Befehl zum neuzeichnen in den EDT. Ob Swing daraufhin neu zeichnet ist Sache der JVM.  d.h. unabhängig vom Fall wird cnt brav weiterlaufen 



Guybrush Threepwood hat gesagt.:


> Ist das wirklich performanter? Ich habe bislang für Animationen immer einen normalen Thread genommen  und über allerlei Tricksereine (z. B. setClip()) versucht, die Performanz zu steigern. Gibt es dazu Quellen, wo das näher beschrieben ist?



Es entfällt zusätzlicher Thread-Overhead, da der Timer in den bereits vorhandenen Timerthread von Java eingefügt wird. Kannst ja mal probieren ob es bei dir was bringt. Der Aufwand ist ja nicht sooo groß


----------



## Quaxli (16. Jun 2009)

@Psypsy:

Hier mal ein Beispiel. Da Du nicht speziell geschrieben hast, wofür die Animation gut sein soll, habe ich es etwas aufwändiger gemacht um ein gleichförmige Bewegung zu gewährleisten.
Das Beispiel ist ein Mittelding. Das Ganze könnte man noch aufwändiger oder einfacher gestalten. Es wäre schön, wenn Du mal detaillierter beschreibst, was Du eigentlich vorhast.
Je nachdem wäre mein Beispiel nämlich überfrachtet oder ausbaufähig 


```
import javax.swing.*;
import java.awt.*;
import java.awt.geom.Rectangle2D;


public class Animation extends JPanel implements Runnable{

	private static final long	serialVersionUID	= 1L;
  JFrame frame;
  Quad quad;
  
  public static void main(String[] args){
  	new Animation();
  }
	
  public Animation(){
  	setPreferredSize(new Dimension(400,400));
  	
  	frame = new JFrame("Beispiel");
    frame.setLocation(100, 100);
    frame.setSize(400,400);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(this);
    frame.pack();
    frame.setVisible(true);
    
    quad = new Quad(0,0,20,20,50,30,this);
    
    Thread t = new Thread(this);
    t.start();
  }
	
	@Override
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		quad.paint(g);
	}
	
	
	
	public void run() {

		long last = System.nanoTime();
		long delta = 0;
		
    while(frame.isVisible()){
    	
    	delta = System.nanoTime() - last;
    	last = System.nanoTime();
    	
    	quad.move(delta);
    	
    	repaint();
    	try {
				Thread.sleep(10);
			} catch (InterruptedException e) {}
    	
    	
    }
		
	}
	
	

}

class Quad extends Rectangle2D.Double{

	private static final long	serialVersionUID	= 1L;
	double speedx;
	double speedy;
	Animation parent;

  public Quad(int qx, int qy, int qw, int qh, int sx, int sy, Animation a){
    super(qx,qy,qw,qh);
    speedx = sx;
    speedy = sy;
    parent = a;
  }
	
	public void paint(Graphics g){
		g.setColor(Color.RED);
		g.fillRect((int)x,(int)y,(int)width,(int)height);
	}
	
	public void move(long delta){
		
		
    if(speedx!=0){
      x += speedx*(delta/1e9);
    }
    
    if(speedy!=0){
      y += speedy*(delta/1e9);
    }
		
		if(x+width<0){
			x = parent.getWidth()-width;
		}
		
		if(y+height<0){
			y = parent.getHeight()-height;
		}
		
		if(x>parent.getWidth()){
			x = -width;
		}
		
		if(y>parent.getHeight()){
			y = -height;
		}
		
		
	}
	
	
}
```


----------



## Schandro (16. Jun 2009)

> "repaint" ist sowieso kein NeuzeichnenBEFEHL sondern nur eine BITTE. Damit legst du nur ein Befehl zum neuzeichnen in den EDT. Ob Swing daraufhin neu zeichnet ist Sache der JVM.  d.h. unabhängig vom Fall wird cnt brav weiterlaufen


Glaubst du ich wüsste das nicht? Les doch einfach mal das durch was ich geschrieben hab und probiers vllt. mal selber aus wenn du mir net glaubst^^



> Zumal du bei einem Thread nicht mal sicher gehen kannst, dass stop auch wirklich stop ist.


Wenn man wirklich so dumm ist und versucht Thread#stop() aufzurufen, ja. Es gibt aber andere auch andere Möglichkeiten...


Ingesamt hab ich Thread hauptsächlich deswegen benutzt, weils IMHO für den TO einfacher zu verstehen ist als ein Timer.


----------



## sl!der (16. Jun 2009)

Huhu Ihrse,

ich habe zu oben gezeigten Quellcode von Quaxli noch eine kurze Frage. Ich beschäftige mich erst seit kurzem mit Java und habe erstmal viel gelesen. Jetzt habe ich mir einfach mal den Quelltext von Quaxli kopiert und ausgeführt - soweit so gut 

Jetzt zu meiner Frage. Wie schaffe ich es z.B. die Frabe des Viereckes während der Bewegung zu ändern? Ich habe es mit einer Zufallszahl versucht die mir dann eine Setter-Methode der Klasse Quad aufruft.


```
switch(zufallszahl){
            case 0: color = new Color(128, 128, 128);
            case 1: color = new Color(0, 0, 0);
            case 2: color = new Color(255, 0, 0);
            case 3: color = new Color(255, 175, 175);
        }

        quad.setcolor(color);
```

diese habe ich in der run method unter quad.move angesiedelt.

Die Quad Klasse habe ich wie folgt erweitert


```
public void paint(Graphics g){
        g.setColor(color);
        g.fillRect((int)x,(int)y,(int)width,(int)height);
    }

    
    public void setcolor(Color c){
        color = c;
    }
```

color ist private der Klasse Quad
....

nur leider ändert sich die Farbe nur 1x - genau beim Start.

Ich hoffe ich habe da jetzt nicht einen essentiellen Aussetzer bei dem Test gehabt, da ich nicht ganz verstehe, warum das Viereck immer nur eine Farbe behält.

Die konkrete Frage: wie änder ich die Farbe des Vierecks in Abhängigkeit von z.B. einer Zufallszahl? :bahnhof:

Danke für Eure Antwort im voraus.


----------



## Schandro (16. Jun 2009)

Du musst den switch-Block jedesmal ausführen wenn du ne andere Farbe haben willst. Wahrscheinlich also jedes mal in der paint-Methode.


----------



## Quaxli (17. Jun 2009)

Zitat aus dem Javabuch von Guido Krüger:



> Nachdem ein case- oder default-Label angesprungen wurde, werden alle dahinterstehenden Anweisungen ausgeführt. Im Gegensatz zu Sprachen wie PASCAL erfolgt auch dann keine Unterbrechung, wenn das nächste Label erreicht wird. Wenn dies erwünscht ist, muß der Kontrollfluß wie in C und C++ mit Hilfe einer break-Anweisung unterbrochen werden. Jedes break innerhalb einer switch-Anweisung führt dazu, daß zum Ende der switch-Anweisung verzweigt wird.



Ich habe Deinen Code zum Farbwechsel mal direkt in die Klasse Quad eingebaut. Es flackert jetzt aber sehr stark. Wenn es langsamer sein soll, mußt Du noch was einbauen, daß den Farbwechsel nur alle x (Milli)Sekunden ausführt.


```
class Quad extends Rectangle2D.Double{

	private static final long	serialVersionUID	= 1L;
	double speedx;
	double speedy;
	Animation parent;
	Color color;

  public Quad(int qx, int qy, int qw, int qh, int sx, int sy, Animation a){
    super(qx,qy,qw,qh);
    speedx = sx;
    speedy = sy;
    parent = a;
  }
	
	public void paint(Graphics g){
		g.setColor(color);
		g.fillRect((int)x,(int)y,(int)width,(int)height);
	}
	
	public void move(long delta){
		
		int zufallszahl = (int)(Math.random()*4);
		
		switch(zufallszahl){
      case 0: color = new Color(128, 128, 128);
        break;
      case 1: color = new Color(0, 0, 0);
        break;
      case 2: color = new Color(255, 0, 0);
        break;
      case 3: color = new Color(255, 175, 175);
        break;
    }
		
    if(speedx!=0){
      x += speedx*(delta/1e9);
    }
    
    if(speedy!=0){
      y += speedy*(delta/1e9);
    }
		
		if(x+width<0){
			x = parent.getWidth()-width;
		}
		
		if(y+height<0){
			y = parent.getHeight()-height;
		}
		
		if(x>parent.getWidth()){
			x = -width;
		}
		
		if(y>parent.getHeight()){
			y = -height;
		}
		
		
	}
	
	
}
```


----------



## -MacNuke- (17. Jun 2009)

Schandro hat gesagt.:


> Glaubst du ich wüsste das nicht? Les doch einfach mal das durch was ich geschrieben hab und probiers vllt. mal selber aus wenn du mir net glaubst^^



Ich habe gelesen was du schreibst. Aber unabhängig ob Thread oder Timer wird es immer 10ms dauern, da der Timer so oder so ausgelöst wird. repaint zeichnet eh nicht neu, die Methode braucht immer gleich lange.



Schandro hat gesagt.:


> Wenn man wirklich so dumm ist und versucht Thread#stop() aufzurufen, ja. Es gibt aber andere auch andere Möglichkeiten...



Jo, man muss den Thread irgendwie abwürgen und irgendwelche Status-Flags setzen. Beim Timer einfach timer.stop() und gut ist.



Schandro hat gesagt.:


> Ingesamt hab ich Thread hauptsächlich deswegen benutzt, weils IMHO für den TO einfacher zu verstehen ist als ein Timer.




```
Timer t = new Timer(10, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                panel.repaint();
            }
        });
        t.start();
```

Ist wesendlich kleiner, ohne Exception-Gedöns und somit einfacher


----------



## Schandro (17. Jun 2009)

> Ich habe gelesen was du schreibst. Aber unabhängig ob Thread oder Timer wird es immer 10ms dauern, da der Timer so oder so ausgelöst wird. repaint zeichnet eh nicht neu, die Methode braucht immer gleich lange.


Ich würd jetzt zwar gerne weiterdiskutieren, aber da du anscheinend nicht fähig bist das richtig zu lesen was ich geschrieben hab lass ichs mal lieber.


----------



## sl!der (17. Jun 2009)

Danke für die Antwort an alle  !

Das mit dem break habe ich gar nicht bemerkt *schäm*!

Bis dann dann sl!der


----------



## Psypsy (17. Jun 2009)

Moin,

Danke erstmal für die Antworten.

@ Schandro: Danke dein Prog hat mir den Stoß vom Schlauch gegeben.:toll:

Dennoch ein paar fragen:

1: Wofür ist der Code


> SwingUtilities.invokeLater(new Runnable() {
> public void run() {
> window.setVisible(true);
> }
> });


in deinem Quelltext???:L Denn ob der drinn ist oder einfach nur "window.setVisible(true);" macht Augenscheinlich keinen unterschied.

2: Macht das einen Unterschied ob man z.B. JFrame im Quelltext aufruft oder es per "extends" einbindet???:L

3: Noch ne Unterschiedsfrage, ich habe es so gelernt und auch in allen Beispielen die ich gesehen habe waren immer ein paar setXXX Methoden in der Main Ihr habt die alle im Konstruktor ist es da einen bestimmeten sinn für???:L
Ok seit dem ich mich jetzt mit der Spielprogrammierung beschäftige sehe ich dies auch öfters.

4: gibt es ein vorteil dafür das man setBounds benutzt statt setLocation & setSize???:L
Ausser das man sich ne Zeile spart.

------------------------------------------------------------------------------

@ Quaxli: Ja Natürlich soll das ganz große Ziel irgendwann mal ein Spiel oder ein paar Spiele werden. Aber dieses Beispiel sollt erstmal nur was kleines,einfaches sein was irgendwas in Bewegung bringt ohne Maus oder Tastatur zu benutzten.

Aber bei dir habe ich auch noch Fragen:

5: Wozu ist


> private static final long   serialVersionUID    = 1L;


diese Zeile da???:L

6: Wollte ich fragen wie man den Thread in gang bekommt wenn man die "run()" nicht mit im Konstruktor hat???:L Wollte abzulut nicht bei mir klappen bis ich dann den teil bei dir mit  " new Thread(this)" gesehen habe und jetzt Funktioniert das auch. Danke:toll:

7:Was bedeutet "1e9" das der Code dort dafür ist immer die gleiche Zeit in Abhängigkeit irgendeiner Schleife zu bekommen ist mir klar. Nur nicht was die Zeichenkombination bedeutet???:L

8: Ein paar fragen die ich dann noch hatte habe ich schon oben bei Schandro gestellt.

Ok dann kommt jetzt erstmal meine Variante von Schandros Prog:
Ich habe es mit dem Swing Timer gemacht, habe aber auch die Variante mit dem Thread drinn und ihn nur auskommentiert. Desweiteren habe ich auch noch die Sachen in der Main und und die Alternative setLocation & setSize zur setBounds auskommentiert da bis ich eine Antwort dazu bekomme ich es als geschmackssache abstemmple.

```
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Fenster extends JFrame { //implements Runnable{
//	Thread t = new Thread(this);
	private int x;
	
	public Fenster() {
		setTitle("Titel");
		setBackground(Color.LIGHT_GRAY);
//		setSize(100,100);
//		setLocation(200, 100);
		setBounds(200,100,600,600);
		add(new Leinwand());
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
		
		t.start();	
	}
  javax.swing.Timer t = new javax.swing.Timer( 10, new ActionListener() {
			public void actionPerformed( ActionEvent e ) { 
				
					x++;
					repaint();
				if(x == 500){
					t.stop();
				}
				} });
//		 wir nehmen den Swing Timer
//	public void run(){
//		System.out.println("Hallo");
//	}
	
	public static void main(String args[]) {
		Fenster hauptfenster = new Fenster();
//		hauptfenster.setBounds(200,100,800,600);
//		hauptfenster.setSize(600, 600);
//		hauptfenster.setLocation(200, 100);
//		hauptfenster.setVisible(true);
		
	}

	private class Leinwand extends JPanel {
		public void paintComponent(Graphics g) {
			super.paintComponent(g);
			Graphics2D g2d = (Graphics2D) g;
			
			g2d.setColor(Color.BLACK);
            g2d.fillRect(x,50,50,50);
				
				
			
		}
	}
}
```

Was haben wir noch auf den Zettel:rtfm:

So ist es jetzt wirklich beim Zeichnen den Swing Timer zuverwenden besser oder nicht???

Da ich hier neu im Forum bin will ich gleich nochmal ein bißchen Schleimen

@ Schandro: Geiler Text


> Insel + Lesen => Threads darf man nicht gewaltsam töten. Man muss sie in den Selbstmord treiben.



@ Quaxli: Schönes Skript (aber beginnt halt schon gleich mit Ereignisempfängern und ich wollte erstmal noch ein davor rumproggen).

Mit freundlichen Grüßen

PsyPsy


----------



## Ebenius (17. Jun 2009)

Psypsy hat gesagt.:


> 1: Wofür ist der Code [...]???:L Denn ob der drinn ist oder einfach nur "window.setVisible(true);" macht Augenscheinlich keinen unterschied.


Alle Veränderungen von GUI-Elementen müssen synchron zum EDT (Event Dispatch Thread) passieren. Oft passiert nichts schlimmes, wenn man diese Regel verletzt; manchmal dann aber doch. Dazu haben viele vieles geschrieben; ich find auf die Schnelle nur [post=511582]meinen früheren Erklärungsversuch[/post].



Psypsy hat gesagt.:


> 2: Macht das einen Unterschied ob man z.B. JFrame im Quelltext aufruft oder es per "extends" einbindet???:L


Theoretisch ganz sicher. Praktisch nicht unbedingt.   Die Formulierung "per \"extends\" einbindet" klingt aber äußerst seltsam. Bist Du sicher, dass Du das Konzept der Vererbung verstanden hast?



Psypsy hat gesagt.:


> 3: Noch ne Unterschiedsfrage, ich habe es so gelernt und auch in allen Beispielen die ich gesehen habe waren immer ein paar setXXX Methoden in der Main Ihr habt die alle im Konstruktor ist es da einen bestimmeten sinn für???:L
> Ok seit dem ich mich jetzt mit der Spielprogrammierung beschäftige sehe ich dies auch öfters.


Methoden werden da aufgerufen wo man sie braucht. Wenn man Dinge im Konstruktor erledigen will, ruft man von dort aus Methoden auf, wenn man sie in einer anderen Methode benötigt, dann ruft man sie eben von da aus auf. Die Frage die man sich immer stellen sollte: Wo gehört die jeweilige Eigenschaft hin. Ist es zum Beispiel Aufgabe des Fensters, direkt nach der Erzeugung geöffnet zu sein, gehört der setVisible(boolean) irgendwo in den Konstruktor (oder eine von diesem aufgerufene Methode). In genau diesem Beispiel sehe ich das grundsätzlich anders; deswegen würde ich das Fenster aus der Main-Methode öffnen. Die Entscheidung was wohin gehört ist aber immer eine Einzelfallentscheidung.



Psypsy hat gesagt.:


> 4: gibt es ein vorteil dafür das man setBounds benutzt statt setLocation & setSize???:L


Man spart eine Zeile und einen zusätzlichen Methodenaufruf (vollkommen unerheblich Performance). Ansonsten kenne ich keinen Unterschied. 



Psypsy hat gesagt.:


> 5: Wozu ist [...] diese Zeile da???:L


Man setzt (am besten) immer eine serialVersionUID wenn man von einer serialisierbaren Klasse ableitet. Diese sollte i.d.R. auch nicht (wie im Beispiel) 1 sein, sondern errechnet werden. Wenn Du mehr dazu wissen möchtest, beschäftige Dich mit dem Thema Serialisierung (findest Tonnen Informationen in den Weiten des Internets und auch hier im Forum). Mein Tipp: Spar Dir das und lass den Teil und das Attribut erstmal weg.



Psypsy hat gesagt.:


> 7:Was bedeutet "1e9" das der Code dort dafür ist immer die gleiche Zeit in Abhängigkeit irgendeiner Schleife zu bekommen ist mir klar. Nur nicht was die Zeichenkombination bedeutet???:L


Einmal zwei hoch neun.

Ebenius


----------



## Quaxli (18. Jun 2009)

zu 5: Das ist die Versionierung - die bastelt Eclipse immer bei mir rein. 
zu 6: Die run() methode eines Threads ruft man nie selbst auf. Threads werden mit start() gestartet. Hast Du ja gesehen 
zu 7: Hat Ebenius ja prinzipiell beantwortet. Der Code an sich bewegt das Viereck in Abhängigkeit der für den letzten Schleifendurchlauf benötigen Zeit - gemessen in Nanosekunden. Da je nach Logik die einzelnen Schleifendurchläufe unterschiedlich lang dauern könnten, erreicht man so eine gleichmäßigere Bewegung (wobei man noch aktiv render müßte, um das richtig zu nutzen).

Noch eine Anmerkung: In Deiner paintComponent-Methode castest Du Graphics nach Graphics2D. Mit dem Code der danach folgt ist das aber unnötig. Wenn da nix Graphics2D-mäßiges mehr kommt, wie z. B. RenderingHints o. ä. kannst Du die Zeile weglassen.

Zum Thema Timer vs. Threads.
Für kleine Spiele/Animationen kann man sich darüber streiten, ob man einen Timer oder einen Thread verwendet. Da ist es letzten Endes wohl Geschmackssache. 
Wenn es Dir darum geht, die FPS (frames per second) nach oben zu treiben, hast Du bei einem Thread mehr Möglichkeiten. Wenn Du dazu mehr wissen willst, guck mal hier: KillerGameProgramming. Die einzelnen Kapitel kann man als PDF runter laden auch wenn es immer etwas versteckt ist. In den ersten 4 Kapiteln steht da so einiges dazu (in Englisch)


----------



## Ebenius (18. Jun 2009)

Quaxli hat gesagt.:


> zu 5: Das ist die Versionierung - die bastelt Eclipse immer bei mir rein.


serialVersionUID ist keineswegs die Versionierung. Im Gegenteil... die serialVersionUID ist dafür da, serialisierte Klassen auch über mehrere Versionen (inhaltlicher Unterschied) als gleich zu markieren. Ist aber für den Themeneröffner derzeit uninteressant.

Ebenius


----------



## Psypsy (18. Jun 2009)

Ok Timer, Thread werde ich berücksichtigen.

Aber nochmal ne frage zum Timer wo liegt eigentlich der unterschied zwischen Swing Timer und der Timer aus Utily?

Ja das mit Graphics2D ist mir klar es soll mal 2 werden und ich hatte einfach schon mal ein wenig rumprobiert und es vergessen wieder zu entfernen.



> Zitat:
> Zitat von Quaxli
> zu 5: Das ist die Versionierung - die bastelt Eclipse immer bei mir rein.
> 
> ...



Als Person mit Interresse an Jave Interressiert es mich, vorallem wenn ich danach frage!

Ich werde mich aber jetzt erstmal im Netz darüber Informieren und gegebenfalls nochmal fragen.

Zu dem "einbinden" ja schlag mich, beiß mich, gib mir Tiernamen das ich gewagt habe beim vererben von einbinden zu reden! Wobei ich bezweifle das von allen die mit Java Programmieren mehr als 5% wissen was Sie da eigentlich genau mit der Vererbung machen ausser das Sie die Methoden oder sonstiges der Oberklasse bekommen und das ganze auch nur so benutzen weil Sie es so irgendwo gesehen haben!!

Da ich zu denen gehöre die sich zu den Lernwilligen anfängern zugehörig fühlt, habe ich nachgefragt wo da genau der unterschied ist. Wenn meine Ausdrucksweise oder Semantik nicht deinen Enormen ansprüchen entspricht entschuldige ich mich und werde zur Strafe heute im Keller bleiben!

Liegt das 1e9 = 1*2^9 jetzt daran das wir nur 0 und 1 zur verfügung haben?
denn sonst steht das e ja für 10^irgendwas also für 1*10^9?
Ansonsten Danke für die Erklärungen

MIt freundlichen Grüßen

PsyPsy


----------



## Quaxli (18. Jun 2009)

1e9 bedeute auch 10 hoch 9


----------



## Ebenius (18. Jun 2009)

Psypsy, ich wollte Dich gar nicht vor den Kopf stoßen. :bahnhof:



Quaxli hat gesagt.:


> 1e9 bedeute auch 10 hoch 9


Du hast natürlich recht und ich nicht nachgedacht. 

Ebenius


----------



## Psypsy (18. Jun 2009)

Ist schon gut , ich hätte ja auch ein wenig auf die Form meines Ausdrucks achten können und ich wollte auch nicht unbedingt recht haben, nur nochmal nachfragen.

Ich habe aber immer noch die Frage, wo da der Unterschied ist.
Das Grundlegende Konzept von Vererbung ist ja Verständlich aber was bringt jetzt die andere Form ausser das ich dann noch irgendwas anders vererben kann.

z.B.

class XXX extends Thread
.
.
JFrame j = new JFrame();

oder macht man dann eher

class XXX
..
..
Thread t = new Thread
JFrame j = new JFrame();

Also ich dachte immer das man das vererbt was man braucht oder wozu die erbende Klasse ausgelegt werden soll.
z.B.

Eine Klasse die ich zu einem Fenster mache erbt von z.B. JFrame und nicht von z.B Thread.
Eine Klasse die ich zum Zeichnen benutze erbt von z.b JPanel

und den rest ruft man dann durch implements (also mit Interfaces) auf oder eben durch Thread t = new Thread();

gibt es da Vorzüge, Bestimmungen, oder sonstiges in dieser Hinsicht?

Mit freundlichen Grüßen

Psypsy


----------



## Schandro (18. Jun 2009)

Du hast ein ziemlich falsches Bild von *OOP*. Les dir bitte die entsprechenden Kapitel darüber in einem Java Buch durch. 

Das Thema ist zu *wichtig* und zu *komplex* als es hier zu besprechen.

z.b. Galileo Computing :: Java ist auch eine Insel (8. Auflage) – 3 Klassen und Objekte


----------



## Psypsy (19. Jun 2009)

Ich bin mir über OOP soweit wie ich es brauche im klaren!
Wenn dich der begriff Mehrfachvererbung stört bessere ich es nach.

ALSO ES GIBT KEINE >MEHRFACHVERERBUNG IN JAVA<!!!

Es sei den, ja jetzt kommts. Also man kann das einbinden sorry das IMPLEMENTIEREN von interfaces via implements auch als Vererbung sehen und dann gibt es die >MEHRFACHVERERBUNG IN JAVA<.
 JA es ist eine Implementierung und keine Vererbung aber das nette Buch auf das du verwiesen hast gibt selbst den anstößlichen Gedanken dazu.

Galileo Computing :: Java ist auch eine Insel (8. Auflage) – 6.13 Schnittstellen

Desweiteren ist im Beispiel der Vererbung sowas zu sehen



> Listing 6.56 com/tutego/insel/game/vd/Playground.java, Ausschnitt
> 
> Room clinic = new Room();
> clinic.name = "Clinic";                 // Geerbtes Attribut
> ...


Galileo Computing :: Java ist auch eine Insel (8. Auflage) – 6.8 Vererbung

Das bedeutet du erbst von verschiedenen Klassen. Warum kommt mir da bloß die Mehrfachvererbung in den sinn?!

Ok wollen wir mal kleinlich sein. Du erzeugst ein Objekt mit einer Referenz auf einer Klasse. Mit dieser Referenz führst du dann die Methoden der Referenzierten Klasse aus.

Das sieht in deinem Bspl.: so aus:

```
public class XXX{
 
    public static void main(String[] args){
        new XXX();}
 
 
    private JFrame window = new JFrame();
    
    public XXX(){
        window.setBounds(100,100,400,200);
        window.add(panel);
```

Bei mir, der direkt mit dem Befehl extends erbt, sieht das, solange ich im Konstruktor bleibe, so aus:

```
public class Fenster extends JFrame { 
	
public Fenster() {
		setBounds(200,100,600,600);
		add(new Leinwand());
```
Beim ausführen gibt es im Ergebnis keinen Unterschied!

Also ich will bestimmt keinen Glaubenskrieg über Vererbung in Java starten. Ich wollte einfach nur wissen was euch dazu bewegt das nicht mit "extends" zu machen.
Denn Ihr benutz XXX y = new XXX(); dazu um an die Methoden in XXX zu kommen ich benutze "extends XXX" dazu auch um zu verdeutlichen wofür die entsprechende Klasse gedacht ist. Wenn Ihr so wollt einen gewissen bauplan vorgeben.


Also wenn Ihr mir keine Antwort dazu geben wollt oder könnt muss ich sie mir woanders suchen, es wäre aber sehr nett wenn Ihr mir antworten könntet.

Es kann ja auch nur macht der Gewohnheit sein, so wie es bei mir Gewohnheit ist in der Klasse direkt von JFrame zu erben und in meiner Inneren Klasse von JPanel. Während Ihr nur eine normale Klasse erzeugt und dann in der Klasse über die Objekte der Referenezen zu gehen oder über anonyme innere Klasse.

Mit freundlichen Grüßen

Psypsy


----------



## Ebenius (20. Jun 2009)

Eine Klasse leitet man ab, um sie um bestimmte Funktionalität und/oder Eigenschaften zu erweitern. Ein JFrame stellt ein Fenster dar, welches den Sinn hat, alle notwendigen Funktionen und alle benötigten Eigenschaften bietet, um verschiedene andere Kontainer zu tragen, diese anzuzeigen, etc.

Wenn ich ein Fenster benötige auf dem verschiedene Panele zu sehen sind, dann benutze ich ausschließlich in JFrame vorhandene Mechanismen. Also gibt es aus Sicht der Fenster-Implementierung keinerlei Erweiterung. Daher leite ich nicht von JFrame ab, sondern benutze einfach ein JFrame.

Wenn ich hingegen ein Fenster bauen möchte, welches sich anders verhält als ein JFrame - zum Beispiel wenn es abgerundete Ecken haben soll und einen halbdurchsichtigen Inhalt - würde ich davon ausgehen, dass ich die Funktionalität und Eigenschaften eines JFrame erweitere. In dem Fall wäre also Vererbung das richtige.

Man kann sich in vielen Fällen sicher streiten. Aber jedesmal eine Ableitung von einer Klasse zu bilden, obwohl man nur deren vorgefertigte Funktionalität steuert oder deren Eigenschaften mit Werten belegt, halte ich für einen kapitalen Fehler.

Ich hoffe, das hilft Dir ein Stück weiter. Und ich hoffe, aus diesen Aussagen erwächst keine Grundsatzdiskussion. 

Guten Abend wünscht Ebenius


----------

