Paint() wird scheinbar nicht richtig ausgeführt

LIO-GmbH

Mitglied
Hallo liebe Community,

wir haben versucht ein Vier Gewinnt zu programieren. Ursprünglich um uns ein wenig an einer guten KI zu versuchen. Leider scheiterte das schon im Ansatz daran, dass unsere grafische Darstellung nicht so ausgeführt wird, wie wir es uns vorstellen. Um erlich zu sein, wissen wir nicht genau wo das problem liegt. Die Vermutung besteht allerdings darin, dass aus unbekannten Gründen die Standartmethode Paint() nicht ausgeführt wird. Unser Stil ist noch nicht ganz ausgereift, das wissen wir, dennoch bitten wir darum, dass ihr euch das mal anschaut und eure Ideen postet.

Hier der Code:

Java:
public class Vier_Gewinnt extends JPanel implements Runnable, KeyListener, ActionListener {

    //Variablen Deklaration
    static Vier_Gewinnt vg;
    public static int[][] iFeld = new int[7][6];
    public JFrame fHead;
    public JPanel pPanel;
    static Dimension dSz;
    static int c;
    static int d;
    static ImageIcon imgIGelb;
    static ImageIcon imgIRot;
    static ImageIcon imgILeer;
    static Image imgGelb;
    static Image imgRot;
    static Image imgLeer;
    static Image backBuffer;

    public static void main(String[] args) {

        //Bilder laden aus src - Ordner
        try {
            imgIGelb = new ImageIcon(ImageIO.read(new File("FeldGelb.jpeg")));
            imgIRot = new ImageIcon(ImageIO.read(new File("FeldRot.jpeg")));
            imgILeer = new ImageIcon(ImageIO.read(new File("FeldLeer.jpeg")));
            System.out.println("Bild: " + imgIGelb);
        } catch (IOException ex) {
            Logger.getLogger(Vier_Gewinnt.class.getName()).log(Level.SEVERE, null, ex);
        }
        imgGelb = imgIGelb.getImage();
        imgRot = imgIRot.getImage();
        imgLeer = imgILeer.getImage();
        vg = new Vier_Gewinnt();
    }

    public Vier_Gewinnt() {

        //Bildschirmgröße auslesen und für weitere Anpassungen vorbereiten
        dSz = Toolkit.getDefaultToolkit().getScreenSize();
        c = 800 * (dSz.width / 800);
        d = 600 * (dSz.height / 600);

        //Frame erstellen und definieren
        fHead = new JFrame();
        fHead.setUndecorated(true);
        fHead.setLayout(null);
        fHead.setBounds((int) ((dSz.width / 2) - (c / 2)), (int) ((dSz.height / 2) - (d / 2)), c, d);
        fHead.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        //Buttons erstellen und dem Frame zufügen
        JButton bStart = new JButton("Start");
        bStart.setPreferredSize(new Dimension(100, 50));
        bStart.setBounds(700 * (dSz.width / 800), 0, 100, 50);
        fHead.add(bStart);
        JButton bEnd = new JButton("Ende");
        bEnd.setPreferredSize(new Dimension(100, 50));
        bEnd.setBounds(700 * (dSz.width / 800), 550 * (dSz.height / 600), 100, 50);
        fHead.add(bEnd);

        //Panel erstellen, definieren und zufügen
        pPanel = new JPanel();
//        pPanel.setBackground(Color.red);
        pPanel.setBounds(0, 0, 700, 600);
        pPanel.setPreferredSize(new Dimension((c - (100 * (dSz.width / 800))), d));
        fHead.add(pPanel);

        fHead.setVisible(true);

        //Buttonfunktionen einrichten
        bEnd.addMouseListener(new java.awt.event.MouseAdapter() {

            @Override
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                System.exit(0);
            }
        });
        for (int a = 0; a <= 6; a++) {
            for (int b = 0; b <= 5; b++) {
                iFeld[a][b] = 0;
            }
        }
        bStart.addMouseListener(new java.awt.event.MouseAdapter() {

            @Override
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                System.out.println("start!");
                backBuffer = pPanel.createImage(pPanel.getWidth(), pPanel.getHeight());
                zeichnen();
            }
        });
    }

    //<editor-fold defaultstate="collapsed" desc="Noch zu definierende Funktionen">
    @Override
    public void run() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    
    @Override
    public void keyTyped(KeyEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    
    @Override
    public void keyPressed(KeyEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    
    @Override
    public void keyReleased(KeyEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    
    @Override
    public void actionPerformed(ActionEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    //</editor-fold>
    
    //Versuch des Umschreibens der Paint Funktionen :(
    @Override
    public void paint(Graphics g) {
        super.paint(g);
        zeichnen();
        System.out.println("paint");
    }

    @Override
    public void paintComponent(Graphics g) {
        System.out.println("UHH");
        super.paintComponent(g);
        zeichnen();
    }

    //Funktion zum zeichnen des Feldes
    public void zeichnen() {
        Graphics g = backBuffer.getGraphics();
        for (int e = 0; e < 7; e++) {
            for (int f = 0; f < 6; f++) {
                if (iFeld[e][f] == 0) {
                    g.drawImage(imgLeer, e * 100, f * 100, 100, 100, this);
                } else if (iFeld[e][f] == 1) {
                    g.drawImage(imgRot, e * 100, f * 100, 100, 100, this);
                } else if (iFeld[e][f] == 2) {
                    g.drawImage(imgGelb, e * 100, f * 100, 100, 100, this);
                } else {
                    System.out.println("Arrayfehler!");
                }
            }
        }
        System.out.println("zeichne" + imgLeer.getSource());
    }
}

Ich hoffe ihr versteht unser Problem (wir nämlich nicht!).
Danke!
 
das Vier_Gewinnt-Panel ist nicht in die GUI eingebunden, schmeiße das Attribut pPanel weg,
und die meisten dessen Vorkommen durch 'this' ersetzen

in den Listener gehört noch ein repaint();
in den Zeichnen-Methoden musst du aufpassen ob backBuffer nicht noch anfangs null ist,

backBuffer selber muss schließlich in paintComponent() dann auch gemalt werden,
nur drauf zeichnen und es nie zeigen, das wird ein vergessenes Meisterwerk

die paint-Methode ganz entfernen, paintComponent() ist korrekt
 
Oh ja... sag' ich mal.
1. siehe SlaterB
2. Wenn man an der Methode "zeichnen()" festhalten will (man kann sie ja immer noch aus "paintComponent()" aufrufen) ist es wichtig, dieser das Graphics-Objekt mitzugeben, statt es in dieser neu initialisieren zu lassen (von wegen, vergessenes Meisterwerk... überflüssiges SonstwasWerk. Swing "backbufferd" standardmässig von Haus aus 😉).
 
Also, schonmal danke für die Tipps.

Wir haben mal versucht das ganze umzusetzen. Leider ohne richtigen Erfolg.
Wir haben versucht, das ganze, was wir in die zeichnen() Methode geschrieben haben im Vier_Gewinnt() auszuführen. Ergebnis: Man sieht kurz, das zu Zeichnende.
Außerdem haben wir festgestellt, dass sich aus unserem Vier_Gewinnt() kein Graphics Objekt ziehen lässt (also mit this.getGraphics() gibts ne nullpointerexception). Woran liegt das?

Grüße
 
niemals getGraphics() von GUI-Komponenten benutzen, von Images ok,
getGraphics() des Panels liefert null, bevor es aus dem Bildschirm zu sehen ist und später sind dort Zeichungen reichlich unbeständig, wie du beides festgestellt hast

paintComponent() zeichnet, da hast du dann auch gleich ein Graphics-Objekt, fertig, bitte nicht zu modifizieren versuchen bevor du nicht selber gewisse Experten-Kenntnisse hast (theoretisch geht vieles)

ansonsten wirds langsam vage mit den Fehlern, wie ist denn der aktuelle Code aus,
idealerweise mit getGraphics() schon überwunden (auf Bildern weiterhin ok),
also die neuesten Erkenntnisse bereits eingebunden?
 
Also, wir haben jetzt auch getGraphics() komplett rausgestrichen. Leider ist mir immer noch nicht klar, 1.) warum wir im Konstruktor nicht mit this auf den frame zugreifen können und 2.) er unsere ausgabe in paintComponent() nicht ausgibt... er also scheinbar nicht darauf zugreift, trotz dem repaint() beim Listener und hier liegt denke ich auch irgentwo der Fehler, weil wenn er painComponent() nicht ausführt, führt er auch zeichen() nicht aus...

--> Ende vom Lied, same problem anyway!???:L

Java:
public class Vier_Gewinnt extends JPanel implements Runnable, KeyListener, ActionListener {

    //Variablen Deklaration
    static Vier_Gewinnt vg;
    public static int[][] iFeld = new int[7][6];
    public JFrame fHead;
    static Dimension dSz;
    static int c;
    static int d;
    static ImageIcon imgIGelb;
    static ImageIcon imgIRot;
    static ImageIcon imgILeer;
    static Image imgGelb;
    static Image imgRot;
    static Image imgLeer;
    static Image backBuffer;

    public static void main(String[] args) {
        //Bilder laden aus src - Ordner
        try {
            imgIGelb = new ImageIcon(ImageIO.read(new File("FeldGelb.jpeg")));
            imgIRot = new ImageIcon(ImageIO.read(new File("FeldRot.jpeg")));
            imgILeer = new ImageIcon(ImageIO.read(new File("FeldLeer.jpeg")));
            System.out.println("Bild: " + imgIGelb);
        } catch (IOException ex) {
            Logger.getLogger(Vier_Gewinnt.class.getName()).log(Level.SEVERE, null, ex);
        }
        imgGelb = imgIGelb.getImage();
        imgRot = imgIRot.getImage();
        imgLeer = imgILeer.getImage();
        vg = new Vier_Gewinnt();
    }

    public Vier_Gewinnt() {

        //Bildschirmgröße auslesen und für weitere Anpassungen vorbereiten
        dSz = Toolkit.getDefaultToolkit().getScreenSize();
        c = 800 * (dSz.width / 800);
        d = 600 * (dSz.height / 600);

        //Frame erstellen und definieren
        fHead = new JFrame();
        fHead.setUndecorated(true);
        fHead.setLayout(null);
        fHead.setBounds((int) ((dSz.width / 2) - (c / 2)), (int) ((dSz.height / 2) - (d / 2)), c, d);
        fHead.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        //Buttons erstellen und dem Frame zufügen
        JButton bStart = new JButton("Start");
        bStart.setPreferredSize(new Dimension(100, 50));
        bStart.setBounds(700 * (dSz.width / 800), 0, 100, 50);
        fHead.add(bStart);
        JButton bEnd = new JButton("Ende");
        bEnd.setPreferredSize(new Dimension(100, 50));
        bEnd.setBounds(700 * (dSz.width / 800), 550 * (dSz.height / 600), 100, 50);
        fHead.add(bEnd);

        fHead.setVisible(true);

        System.out.println("zeichne" + imgLeer.getSource());

        //Buttonfunktionen einrichten
        bEnd.addMouseListener(new java.awt.event.MouseAdapter() {

            @Override
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                System.exit(0);
            }
        });
        for (int a = 0; a <= 6; a++) {
            for (int b = 0; b <= 5; b++) {
                iFeld[a][b] = 0;
            }
        }
        bStart.addMouseListener(new java.awt.event.MouseAdapter() {

            @Override
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                fHead.repaint();
                System.out.println("start");
            }
        });
    }

    //<editor-fold defaultstate="collapsed" desc="Noch zu definierende Funktionen">
    @Override
    public void run() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void keyTyped(KeyEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void keyPressed(KeyEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void keyReleased(KeyEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
    //</editor-fold>

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        zeichnen(g);
        System.out.println("pc");
    }

//    Funktion zum zeichnen des Feldes
    public void zeichnen(Graphics g) {
        for (int e = 0; e < 7; e++) {
            for (int f = 0; f < 6; f++) {
                if (iFeld[e][f] == 0) {
                    g.drawImage(imgLeer, e * 100, f * 100, 100, 100, this);
                } else if (iFeld[e][f] == 1) {
                    g.drawImage(imgRot, e * 100, f * 100, 100, 100, this);
                } else if (iFeld[e][f] == 2) {
                    g.drawImage(imgGelb, e * 100, f * 100, 100, 100, this);
                } else {
                    System.out.println("Arrayfehler!");
                }
            }
        }
        System.out.println("zeichne" + imgLeer.getSource());
    }
}
 
Du fügst die VierGewinnt Instanz niemals dem Frame hinzu.

Übliche Vorgehensweise ist übrigens, dass man entweder von JFrame erbt und in dessen Konstruktor die Initialisation vornimmt, oder das Frame in der main-Methode intialisiert.
 
das VierGewinnt-Objekt vg ist nicht ins JFrame eingebunden..

der statischen Variable wird das Objekt in der main aber auch erst zugewiesen, wenn der Konstruktor fertig ist,
recht spät, im Konstruktor könntest du vg nicht benutzten,
es sei denn dort findet die Zuweisung statt, etwa
vg = this;

oder eben mit this arbeiten

> warum wir im Konstruktor nicht mit this auf den frame zugreifen können
bleibt leider eine Frage ohne Code oder jede Erklärung,
this ist natürlich hier ein Panel und kein Frame, sonst gibt es keine Probleme mit this im Konstruktor
 
Okay, danke für all eure Hilfen. Leider ist es uns bisher nicht gelungen das alles so umzusetzen, wie wir es gerne hätten.
Dennoch war es überaus hilfreich für die weitere Programierung. Wir versuchen jetzt das ganze jetzt per, von Netbeans vorgegebener GUI.

Grüße
lio
 

Zurück
Oben