# Mehrere sich bewegende Objekte in einem Frame



## TheDescent (8. Nov 2010)

Hallo

Ich möchte gerne zwei sich bewegende Objekte in einem Frame darstelln, und komme nun nicht weiter , da immer nur das zuletzt hinzugefügte Objekt in dem Frame läuft, aber nicht beide gleichzeitig....

Im Folgenden quellcode besitzen die Klassen Robutton und Münzen Jeweils methoden , die mithilfe eines Timers ,actionListener, und der repaint methode sich immer wieder aufrufen und sich somit bewegen, 

Habe schon einiges versucht aber noch nichts hat wirklich funktioniert, 
bitte um euren Rat



[JAVA=42]

private  Robutton robo;	
private  Münze coin;

public Tisch(){

    robo = new Robutton(200,200);
    coin = new Münze(50,100);

    JFrame Fenster =new JFrame();
    Fenster.add(coin);
    Fenster.add(robo);
    Fenster.setTitle("Robuttons");
    Fenster.setSize(300,280);
    Fenster.setDefaultCloseOperation(EXIT_ON_CLOSE);
    Fenster.setVisible(true); 
    Fenster.setResizable(true);
    Fenster.setLocationRelativeTo(null);

	}
[/code]


----------



## Marco13 (8. Nov 2010)

Hängt wohl auch mit dem Layout zusammen. Die beiden Klassen erben wohl von JComponent - ich find's ja häßlich, Sprites von JComponent erben zu lassen, aber das kriegt man irgendwie nicht ausgerottet. Mach' mal ein 
frame.getContentPane().setLayout(null);
frame.getContentPane().add(coin);
frame.getContentPane().add(rob);
Falls dann nichts erscheint, müssen noch die Bounds der beiden Objekte passend gesetzt werden
coin.setBounds(x,y,w,h);
oder 
coin.setSize(w,h);
coin.setLocation(x,y);
oder so...


----------



## TheDescent (9. Nov 2010)

Zeigt Leider keine Wirkung... nun wird gar nichts mehr dargestellt, nicht mal wenn ich nur ein Objekt hinzufüge.. gibt es noch andere möglichkeiten ?


----------



## Marco13 (9. Nov 2010)

Ein KSKB würde helfen.


----------



## SlaterB (9. Nov 2010)

überlege doch mal logisch, was sollte es anderes geben?
du hast eine Zeichenfläche, da kannst du einfach nur
1) fertige Komponenten pixelgenau platzieren, funktioniert auch wenn man es richtig macht, Code posten
2) vorgegebene Layouts verwenden die einen Teil der Arbeit erledigen, dann weniger Arbeit (nur add() aufrufen) aber auch weniger exakten Einfluss,
und natürlich muss man die Layouts kennen, etwa dass der Standard BorderLayout nur eine Komponente per einfachem add() akzeptiert, Bedienungsanleitung lesen
3) keine fertigen Komponenten setzen sondern paintComponent überschreiben, und mit Zeichenbefehlen Pixel für Pixel bemalen


----------



## TheDescent (9. Nov 2010)

Da ich noch nicht sehr viel erfahrung mit der Gui hab zeige ich euch am besten die beiden klassen Robutton und Münze, ich hoffe ihr könnt dort den fehler entdecken, weiß nicht mehr weiter, danke für die Tipps aber leider halfen sie mir bisjetzt noch nicht 







Die Robutton Class


```
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import javax.swing.Timer;
import java.util.Random;
import javax.swing.JFrame;

public class Robutton extends JPanel implements ActionListener {


 
 
	
 Timer timer;
 private int x, y;
 private int xdir,ydir;

 
 
       public  Robutton(int x,int y) {
      
    
       timer = new Timer(25, this);
       timer.start();
   
       this.x = x;
       this.y = y;
      
       
       Random r = new Random();
       switch(r.nextInt(4)){
       
       case 1:
       
       xdir =(-1);
       ydir =(-1);   
       
       break;
       
       case 2:
       xdir=(1);
       ydir=(1);   
       break ;
       
       case 3:
       xdir =(-1);
       ydir =(1);   
       break;
       
       
       case 4:
    	   
       xdir=(1);
       ydir=(-1);   
       break;
       
       default:
       xdir=(0);
       ydir=(-1);   
       }}   
   

    
    public void paintcomponent(Graphics g) {
    
    	super.paint(g); 

        Graphics2D g2d = (Graphics2D)g;
        g2d.drawOval(x, y, 10, 10);
        g2d.setColor(new Color(241, 98, 69));
     	g2d.fillOval(x, y, 20, 20);
   	
    }


    public void actionPerformed(ActionEvent e) {
        
        x += xdir;
        y += ydir;
       
      
        
        if (y==0){
        
           setxdir(0);
           setydir(1);
        	
        }
        if (x==0){
            
            setxdir(1);
            setydir(0);
            	
            	
            }
        if (y==225){
            
            setxdir(0);
            setydir(-1);
            	
            	
            }
        if (x==264){
            
            setxdir(-1);
            setydir(0);
            
            	
            }
    

    	repaint();  
   
    	 }  	
 
public void setxdir(int x){
	xdir =x+xdir;
}
public void setydir(int y){
	ydir =y+ydir;
}
public void setx(int x){
	this.x+=x;
}
public void sety(int y){
	this.y+=y;
}

public  int getxdir(){
	return xdir;
}	
public int getydir(){
	return ydir;  
	 
  }	
public  int getx(){
	return 	x;
}	
public int gety(){
	return y;  
	 
}



}
```

Die Münze class




```
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JPanel;
import javax.swing.Timer;

public class Münze  extends JPanel implements ActionListener {
    
	Timer timer;
	private int x, y;
	 
	
	
	public Münze(int x , int y){
	
		

    timer = new Timer(25, this);
	timer.start();	
		
	this.x = x;
	this.y = y;
	
	}
	
    public void paintcomponent(Graphics g) {
		  super.paint(g);   


     Graphics2D g2d = (Graphics2D) g;	
     	    
        
         g2d.drawOval(x, y, 10, 10);
   	 g2d.setColor(new Color(130, 100, 84));
   	 g2d.fillOval(x, y, 20, 20);
     

   	 
	}
	public void actionPerformed(ActionEvent e) {
	

		
	repaint();

        }
	
	
	
	public void setx(int x){
		this.x =x;
	}
	public void sety(int y){
		this.y =y;
	}
	public  int getx(){
		return x;
	}	
	public int gety(){
		return y;  



}}
```


----------



## Marco13 (9. Nov 2010)

*drüberscroll*
public void paintcomponent(Graphics g) { :autsch:
public void paintComponent(Graphics g) { !!!
und innen super.paintComponent aufrufen...


----------



## SlaterB (9. Nov 2010)

> public void paintcomponent(Graphics g) {
>          super.paint(g);   

super.paintComponent(g); 
aufrufen!
und c groß schreiben, so wird bisher ja überhaupt nix gemalt, richtig?

-----

ansonsten interessant, du verwendest also (schon immer oder neu?) von meinen genannten Ansätzen die Nummer 3)

dazu ist es wirklich nicht so leicht zwei Komponenten zu haben, die im selben Bereich malen,
normalerweise herscht jedes Panel über seinen eigenen Bereich, der super.paintComponent(g); löscht ja auch die Zeichenfläche,

besser wäre es, wenn die beiden Komponenten kein JPanel sind sondern einfache normale Klassen mit paint-Methoden,
dann brauchst du EIN JPanel, welches in die GUI eingefügt wird, und an dem repaint() aufgerufen wird,
und dieses eine JPanel ruft in seiner paintComponent-Methode die paint der beiden Klassen Robutton + Münze auf

komplizierte Aufgabe..


----------



## TheDescent (9. Nov 2010)

Danke, ich werd mal versuchen alles über ein JPanel laufen zu lassen, bis spätestens morgen sag ich dann bescheid wies gelaufen ist


----------



## TheDescent (9. Nov 2010)

So, habe jetzt versucht das ganze in die tat umzusetzen, habe aber an folgendem problem: 
Robutten und Münze sind nicht akzeptierte componenten, wenn ich sie in in ein Panel einfügen will, was muss ich also tun? ,  habe  diesmal die repaint methode in einem ActionListener untergebracht, 
und male die jeweiligen Objekte mit ihrer paint methode. 

Angefügt liegt noch einmal die jetzige paintmethode der beiden Klassen Robutton und Münze vor (falls sich dort wieder ein Fehler eingeschlichen habe sollte ----> wie gesagt ich programmiere noch nicht lange mit der Gui )







```
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import javax.swing.JFrame;
import javax.swing.Timer;
import java.awt.*;

public class Tisch extends JFrame implements ActionListener{ 

private  Robutton robo;	
private  Münze coin;
private  MünzenList coins; 
private  boolean aufsammeln;
Timer timer;

	
	public Tisch  (){
	

	timer = new Timer(25, this);
	timer.start();
	
		
		
    robo =new Robutton(50,100);	
    coin = new Münze(100,200);	
    JFrame frame = new JFrame();
    JPanel pan = new JPanel();
    pan.add(coin);
    pan.add(robo);
    pan.paintComponents(getGraphics());
    frame.add(pan);
    frame.setTitle("Robuttons");
    frame.setSize(300,280);
    frame.setDefaultCloseOperation(Tisch.EXIT_ON_CLOSE);
    frame.setVisible(true);
    frame.setResizable(true);
	
	
	
	
	
	}


	
	public void actionPerformed(ActionEvent p){
	
		
		robo.paint(getGraphics());
		coin.paint(getGraphics());
		
		repaint();
		
		
		

		
	}
```

  Paint methode:   


```
public void paint(Graphics g) {
    
        Graphics2D g2d = (Graphics2D) g;
        g2d.drawOval(x, y, 10, 10);
        g2d.setColor(new Color(241, 98, 69));
     	g2d.fillOval(x, y, 20, 20);
```


----------



## SlaterB (9. Nov 2010)

der eine oder mehrere Timer rufen wie bisher repaint() beim JPanel auf, und zwar bei dem einzigen jetzt noch verbleibenden Panel,
mehr ist dort nicht zu tun,

in der paintComponent-Methode des JPanels ist dann das Graphics-Objekt verfügbar, das an die beiden zu zeichnenden Objekte übergeben,
niemals getGraphics() aufrufen


----------



## Michael... (9. Nov 2010)

Warum erzeugst Du in einem JFrame einen zweiten JFrame. Ein Aufruf von getGraphics() auf Komponenten sollte man nur machen, wenn man weiss was man tut. In Deinem Fall sollte es sogar null zurückgeben und selbst wenn was vernünftiges zurückkommen sollte, der JFrame auf dem Du diese Methode aufrufst ist vermutlich gar nicht sichtbar.
Gezeichnet wird nur innerhalb einer paintComponent() einer Komponente.

Eine Einführung dazu gibt's z.B. hier:
JavaInsel Graphikprogrammierung


----------



## TheDescent (9. Nov 2010)

Ok, Prinzipiell Verstanden, jedoch bekomm ichs in der umsetzung  nicht hin, g müsste das graphic object sein, wird aber nicht erkannt,  wäre es möglich das sich jemand erbarmt mir einen "korrigierten"
Quellcode zu geben? denke es wäre sehr hilfreich 

Nochmals danke für die bisherige Hilfe 




```
robo =new Robutton(50,100);	
    coin = new Münze(100,200);	
	
    JPanel pan = new JPanel();
    pan.add(coin.paint(g));
    pan.add(robo.paint(g));
    pan.paintComponents(g);
    
    add(pan);
    setTitle("Robuttons");
    setSize(300,280);
    setDefaultCloseOperation(Tisch.EXIT_ON_CLOSE);
    setVisible(true);
    setResizable(true);
	
	}


	
	public void actionPerformed(ActionEvent p){
	
	repaint();
		
	
	}
```


----------



## SlaterB (9. Nov 2010)

das Prinzip ist wie mehrfach erwähnt, aus der überschriebenen paintComponent des Panels die paint-Methoden der anderen Objekte aufzurufen,
paintComponent hattest du doch bisher auch, das hängt doch mit repaint() und überhaupt allen g-Zeichen-Befehlen zusammen, 
wie kannst du sagen, das verstanden zu haben aber dann diese zentrale Methode überhaupt nicht (mehr)  verwenden?!

und Code-Befehle wie
> pan.add(coin.paint(g));
sind vollkommen ausgedachter Nonsens, dann sag doch einfach dass du noch nichts verstanden hast..


```
robo =new Robutton(50,100); 
    coin = new Münze(100,200);  
    
    JPanel pan = new JPanel() { // anonyme Klasse oder wieder eine eigene neue Klasse definieren
       public void paintComponent(Graphics g) { 
           super.paintComponent(g); // immer gut

           coin.paint(g); // ganz einfach, als ständen die Zeichenbefehle hier, auf g des Panels irgendwas malen
           robo.paint(g);
       }
    };
```


----------



## TheDescent (10. Nov 2010)

Supi so läuft alles wie ichs wollte, vielen vielen Dank, :applaus::applaus: , hatte wohl dann doch den Ansatz falsch verstanden ; )


----------

