JPanel wird zweimal hinterinander gezeichnet.. Wieso?

Zuerstmal der Code:

Klasse Beute:
Java:
import java.awt.geom.Rectangle2D;
import java.awt.Graphics;
import java.awt.Color;

public class Beute extends Rectangle2D.Double
{
    int width;
    int heigth;
    int x;
    int y;
    
    public Beute(int x, int y, int width,int heigth)
    {
        this.x = x;
        this.y = y;
        this.width = width;
        this.heigth = heigth;
    }
    
    public void paintComponent(Graphics g) {
        g.setColor(Color.GREEN);
        g.fillOval(x,y,width,heigth);
    }
}
Klasse Raeuber
Java:
import java.awt.geom.Rectangle2D;
import java.awt.Graphics;
import java.awt.Color;

public class Raeuber extends Rectangle2D.Double
{
    int width;
    int heigth;
    int x;
    int y;
    
    public Raeuber(int x, int y, int width,int heigth)
    {
        this.x = x;
        this.y = y;
        this.width = width;
        this.heigth = heigth;
    }
    
    public void paintComponent(Graphics g) {
        g.setColor(Color.BLUE);
        g.fillOval(x,y,width,heigth);
    }
}
Klasse Tile:
Java:
import java.awt.geom.Rectangle2D;
import java.awt.Graphics;
import java.util.Random;

public class Tile extends Rectangle2D.Double
{
    int x;
    int y;
    int width;
    int heigth;
    
    boolean test = false;

    public Tile(int x, int y, int width, int heigth)
    {
        this.x = x;
        this.y = y;
        this.width = width;
        this.heigth = heigth;     
    }

    public void paintComponent(Graphics g) {
        g.drawRect(x,y,width,heigth);
    }

    void addShapes(Rectangle2D.Double shape, Graphics g) {
        if(shape instanceof Beute) {
            Beute beute = (Beute)shape;
            beute.paintComponent(g);
            test = true;
        }
        else if(shape instanceof Raeuber) {
            Raeuber raeuber = (Raeuber)shape;
            raeuber.paintComponent(g);
            test = true;
        }
    }
    
    boolean checkShapes() {
        return test;
    }
}
Klasse Map:
Java:
import java.util.Random;
import java.awt.Graphics;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;

public class Map
{
    Tile[][] tiles;
    Random r;

    public Map() {
        tiles = new Tile[6][6];
        r = new Random();
    }

    void drawRandom(Graphics g) {
        for(int i = 0; i < 6; i++) {
            for(int j = 0; j < 6; j++) {    
                int zufall = r.nextInt(3);
                if(zufall == 0){
                    tiles[i][j].addShapes(new Beute((100*j) + 25,(100*i) + 25,50,50), g);
                }
                else if(zufall == 1) {
                    tiles[i][j].addShapes(new Raeuber((100*j) + 25,(100*i) + 25,50,50), g);
                }
                else {
                }
            }
        }
    }

    void draw(Graphics g) {
        for(int i = 0; i < 6; i++) {
            for(int j = 0; j < 6; j++) {
                tiles[i][j] = new Tile(100 * j, 100 * i, 100, 100);
                tiles[i][j].paintComponent(g);     
            }
        }
    }
}
Klasse Fenster:
Java:
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Graphics;

public class Fenster extends JFrame
{
    Map map;
    
    public Fenster(Map m)
    {
        super("Biologie-Game");
        
        this.map = m;
        
        setSize(600,628);
        setResizable(false);
        
        MyPanel panel = new MyPanel();
        
        add(panel);
        setVisible(true);
    }
    
    class MyPanel extends JPanel {
        public MyPanel() {
            setSize(600,600);
        }
        
        public void paint(Graphics g) {
            super.paintComponent(g);
            
            map.draw(g);
            map.drawRandom(g);
        }
    }
}
Beim Erzeugen eines neuen Fensters werden die Tiles ausgegeben(auch mit den Kreisen). Nach ca. einer Millisekunde verändern sich die Positionen der Kreise(das Panel zeichnet sich neu) und beim ausgeben von checkShapes() auf die Konsole kommen zwei Werte raus.
Sieht dann ungefährt so aus:

Bei folgendem Methodenaufruf: tiles[0][3].checkShapes();

Fenster "ploppt" auf --> Konsole zeigt true an
Danach verändert sich der Inhalt des Panels z.B Kreise waren an den Position [0][6],[0][3] und [5][4] und sind auf einmal an [1][3],[2][4] und [5][5] --> Konsole zeigt false.

Meine Frage ist nun wieso das Panel sofort wieder neu gezeichnet wird und wie ich den Fehler ausmerzen kann.

Mfg, Zitrus
 
Zuletzt bearbeitet:
Du hast eine große Menge an wiederholtem Code. Dafür gibt es Vererbung.
Du hast paint überschrieben. In Swing sollte es paintComponent sein.

Warum es nun zwei mal aufgerufen wird, weiß ich grade nicht aber das Problem liegt darin, dass du paintRandom hast. Darin wird jedes Mal eine neue Zufallswelt generiert. Du solltest eher initRandomWorld haben, was ein mal aufgerufen wird, mehrere Parameter initialisiert und auf diese Parameter greift die noch zu implementierende Methode paintWorld zu.
 
Aber ich muss doch erst die Methode draw() und dann die Methode drawRandom() ausführen, da ich sonst ja eine NullPointerException kriege, weil keine Tiles vorhanden sind denen man eine Grafik hinzufügen könnte. Oder habe ich deine Antwort falsch verstanden?

PS: Hatte zu Beginn auch die paintComponent Methode im Panel. Hat auch nicht geklappt.
PS'S: Wo wiederhole ich denn Code? (Mal Abgesehen von der Beute und Raeuber Klasse)
 
Zuletzt bearbeitet:
Hi nochmal,

Habe jetztmal testhalber die Methode draw() mit einem System.out.println() bestückt.
Java:
 void draw(Graphics g) {
        for(int i = 0; i < 2; i++) {
            for(int j = 0; j < 2; j++) {
                tiles[i][j] = new Tile(100 * j, 100 * i, 100, 100);
                tiles[i][j].paintComponent(g);  
                
                System.out.println("Tile" + "[" + i + "]" + "[" + j + "]" + tiles[i][j].x );
Ich erhalte beim erzeugen eines neuen Fensters folgende Ausgabe:

Tile[0][0]0
Tile[0][1]100
Tile[1][0]0
Tile[1][1]100
Tile[0][0]0
Tile[0][1]100
Tile[1][0]0
Tile[1][1]100
Ich verstehe immer noch nicht wieso es doppelt ausgegeben wird.
@Gucky könntest du mir vielleicht nochmal erklären was ich verändern soll? Es tut mir wirklich leid aber habe deine Antwort leider nicht so ganz verstanden.
 
Es gibt eine Methode namens repaint(). Diese wird immer aufgerufen, wenn irgendetwas am Container verändert wird. So z.B. die Größe.
Ich könnte mir vorstellen, dass es an setSize liegt. Du könntest mal vor und nach setSize eine Ausgabe machen, um das herauszufinden.

initRandomWorld würde auch nichts zeichnen sondern bspw. im Konstruktor von Map aufgerufen werden und nur die Positionen der Tiles definieren.

Trotzdem solltest du paintComponent überschreiben. Und vergiss nicht die preferredSize zu setzen.

Genau dort widerholst du Code ;)
 
Passende Stellenanzeigen aus deiner Region:

Neue Themen

Oben