Repaint wird nicht durchgeführt

Goldinho

Aktives Mitglied
So, nächste Frage:

Ich habe ein Schachbrett, das auf MausEvents für die Zugeingaben per DragDrop wartet. Das ganze ist ein JLabel namens Screen. Bei jedem Schachzug wird das Schachbrett per repaint() neu gezeichnet. So weit so gut, funktioniert prima. Nun habe ich rechts eine Notation gebaut, wo die einzelnen Züge (als JButtons) angezeigt werden. Man soll darauf klicken und dann wird die Stellung des vergangenen Zuges angezeigt. Klappt auch alles, auf der Konsole wird es mir wunderbar ausgegeben. Wenn ich aber nun die neue Stellung auch graphisch ausgeben möchte, die gewünschte Stellung an meine Klasse Screen übergebe und repaint aufrufe, passiert: NICHTS.

Kann es sein, dass da repaint-Prozesse verweigert werden, solange auf andere gewartet wird? Ich habe da bei der Recherche was gelesen (https://www.oracle.com/technetwork/java/painting-140037.html). Um das zu checken, bin ich aber noch nicht weit genug.

Kann mir das jemand vielleicht etwas didaktisch reduziert erklären und mir nen Tipp geben, wie ich vorgehen soll?

Danke
 
Also repaint markiert nur etwas, dass es neu gezeichnet werden soll. Das ist ein Event, dass vom UI Thread erst verarbeitet werden muss.

Falls Du nun noch irgendwas auf dem UI Thread machst und diesen somit blockiert, dann kann das Element nicht neu gezeichnet werden.

Daher wäre meine Frage: arbeitest Du evtl. länger im UI Thread? Also wenn z.B. Ein Knopf gedrückt wird, dann solltest Du kurz etwas machen und den UI Thread nicht blockieren. Dinge die Zeit brauchen, sollten auf einem eigenen Thread laufen.
 
Eigentlich wird nicht viel gemacht. Es wird die neue Stellung kurz neu gezeichnet, dann die Notation eingetragen und dann auf die nächste Mauseingabe gewartet. Bei der Notation warte ich halt ebenfalls per ActionListener, ob jemand einen Button klickt. Da soll dann eine alte Stellung aufgerufen werden. Aber da passiert dann nichts. Irgendwie scheinen die sich ins Gehege zu kommen.
 
Kannst du den Code zeigen? Ohne Code ist da so erst einmal nicht viel zu sagen fürchte ich.
 
Puh, das wird schwierig, aber ich schau mal, dass ich die entscheidenden Codeschnipsel raushole:

Also, das ist der ActionListener der Buttons in der Notation. Die haben eine Int als Namen bekommen, die ich abrufe, die jeweilige Stellung hole, aufs Brett setze und dann repainten lasse. Leinwand ist ein Objekt der Klasse Screen (JLabel).

Java:
@Override
    public void actionPerformed(ActionEvent e) {
        if(e.getSource() != null){
            String Zugn = ((JButton) e.getSource()).getName();
            int Zugnr = Integer.parseInt(Zugn);
            // Konsolenausgabe passt!
            // System.out.println("Zug: " + Zugnr);
            // Brett1.ausgabeStellung(Zugnr+1);
            Figur[][] B = Brett1.getStellung(Zugnr+1);
            Brett1.setBoard(B);
            Leinwand.repaint();
        }    
    }

Und die zweite Hauptmethode wäre die MouseReleased-Abfrage in der Klasse Screen. Nach allen Checks wird die Figur aufs Board gesetzt (settoboard()) und ganz einfach repaintet.

Java:
public void mouseReleased(MouseEvent e) {
        x = e.getX(); y = e.getY();
        nach_h= x/fieldSize;
        nach_v = 9-y/fieldSize;
        
        if (x >=70 && x <=630 && y >=70 && y <=630) {
        // Zugchecks
        if (checking() == false) {
                // Zurücksetzen
                //Main.sysMessage("Zurücksetzen nach: "+ von_h + "-" + von_v);
                if (fig != null) { brett.settoboard(fig, von_h, von_v); }
                repaint();
            }
            else {
                // Was geschlagen worden?
                if (brett.getFeld(nach_h,  nach_v) != null) { beater = true; } else { beater = false; }
                
                // Figur setzen
                brett.settoboard(null, von_h, von_v);
                brett.settoboard(fig, nach_h, nach_v);
                
                // Enpassanthandling
                if (fig.typ == "b" && brett.getDoEnpassant() != 0) { brett.settoboard(null, nach_h, brett.getDoEnpassant()); brett.setDoEnpassant(0); }
                if (oldEnpassant_h == brett.getEnpassant_h() && oldEnpassant_v == brett.getEnpassant_v()) { brett.setEnpassant(0, 0); }
                else { oldEnpassant_h = brett.getEnpassant_h(); oldEnpassant_v = brett.getEnpassant_v(); }
                //Main.sysMessage("Enpassantflag steht auf: "+brett.getEnpassant_h()+"-"+brett.getEnpassant_v());
    
                // BauenchangeHandling
                if (brett.getBauernchange() == true) { bauernChangeDialog(); }
                    
                
                    // Sound spielen
                    Set.play();   
                    // Farbe wechseln
                    switchTurn();
                    // Schachgebot Gegner, deshalb NACH switch
                    brett.schachtest = true;
                    keinschach = brett.schachcheck(0, 0, Turn);
                    if (keinschach == false) { msgtext += "\nSchach!\n"; Check.play(); }
                    
                    // EndofGameCheck - Matt und Patt
                    brett.mattcheck = true;
                    endofgame = endofgame(brett, Turn);
                    if (endofgame) {
                            if (keinschach) { msgtext += "\nPatt!\n"; }
                            else { msgtext += "\nSchachmatt!\n"; }
                            Gameover.play();
                            }
                    brett.schachtest = false;
                    brett.mattcheck = false;
                    //Main.sysMessage("Ende: "+ endofgame);
                    //Main.sysMessage("----------------------------------------------------------------------");
                    // Rotation
                    rotate_it();
                    
                    // Ausgabe
                    //brett.ausgabe();
                    Main.ausgabe(msgtext);
                    msgtext = "";
                    
                    // Notation
                    //notationtext += notation(fig.typ,von_h, von_v, nach_h, nach_v, beater, movecount);
                    notationtext = notation(fig.typ,von_h, von_v, nach_h, nach_v, beater, movecount);
                    Main.notes(notationtext);
                    
                    repaint();
                    // Stellung speichern
                    brett.addStellung();
                    movecount++;
                }
        }
        else {
            brett.settoboard(fig, von_h, von_v);
            fig = null;
            repaint();
            }
    }


Ich weiß, dass der Code chaotisch ist und lächerliches Naming hat 😉 Ich bin ja noch am Anfang 😉
 
Ich weiß, dass der Code chaotisch ist und lächerliches Naming hat 😉
So lange Bezeichner aussagekräftig sind, spielt es keine Rolle ob sie "lächerlich" sind. Deine Bezeichner haben allerdings das Problem, dass sie sich weder an die Benennungskonventionen von Java halten, noch aussagekräftig sind.

Ich bin ja noch am Anfang 😉
Tipp: klopf den Code in die Tonne und fang von vorne an - aber ohne GUI. Das ist nicht abwertend gemeint, sondern das GUI sorgt dafür, dass Du Deinen Code eben darauf konzentrierst. Tatsächlich ist das UI das, was am wenigsten interessiert und eines der Grundprinzipien lautet, Verantwortlichkeiten zu trennen. Genau das verhinderst Du aktuell erfolgreich, indem Du die Logik in die Oberfläche klopfst. Mach das Spiel textbasiert oder wenn Du magst, einfach über die Kommandozeile (z. B. Stellung einlesen, Zug ausführen, neue Stellung ausgeben). Wenn Du das hast, dann kannst Du eine Oberfläche anbinden.
 
Ich habe ein Drag-and-Drop-Schachprogramm, das komplett bugfrei funktioniert, inclusive Matt-/Patterkennung und aller Sonderzüge. Ich werde da mit Sicherheit erstmal nichts in die Tonne klopfen. Und natürlich habe ich es anfangs textbasiert geschrieben. Aber ja, als Anfänger hat man da nicht immer den Überblick und nach und nach wird der Code unübersichtlicher und am Ende ist es halt doch wieder chaotisch, vermutlich kennst du das aus der Vergangenheit. Ich werde mal versuchen, deinen Text eher als sprachlich ungelenkes Informatikersprech aufzufassen und nicht beleidigt zu sein und in einem nächsten Projekt werde ich versuchen das zu beherzigen.
Dennoch habe ich eine Frage gestellt, deren Beantwortung mir immer noch am Herzen liegt:

Die Repaint-Methode scheint durch den MausListener blockiert zu werden. Programmtechnisch funktioniert sonst alles: Wenn ich nämlich eine Stellung aus der Notation aufrufe, tut sich trotz Repaint erstmal nichts, auf der Konsole wird aber alles perfekt ausgegeben. Wenn ich dann nun einen Zug mit der Maus ausführe, erscheint auch die gewünschte alte Stellung. Das Repaint wird aber erst durch den Mauszug aufgerufen, scheint aber im ActionListener der Buttons ignoriert zu werden.

Also glaubt ihr, dass es nichts mit einer Blockade gestackter Repaint-Prozesse zu tun hat, sondern dass es eher irgendein Bug in meinem Code ist?
 
Zuletzt bearbeitet:
und nicht beleidigt zu sein
Dazu gibt es auch wirklich keinen Grund (habe extra dazugeschrieben, dass das keine Abwertung darstellt). In Deinem Code ist halt Logik und Darstellung vermischt, das ist grundsätzlich schlecht und "in die Tonne klopfen" heißt nicht, alles neu schreiben zu müssen, denn kopiert ist vorhandener Code schnell.

Aber ja, als Anfänger hat man da nicht immer den Überblick und nach und nach wird der Code unübersichtlicher und am Ende ist es halt doch wieder chaotisch, vermutlich kennst du das aus der Vergangenheit.
Das kenne ich nicht nur aus der Vergangenheit 🙂 Und genau darum geht es: wieder Ordnung ins Chaos zu bringen.

Die Repaint-Methode scheint durch den MausListener blockiert zu werden.
Würde der MausListener blockieren, dann würde die ganze GUI einfrieren.
 
Aaaaargh!!!!! Lösung gefunden.

Ich habe vergessen, dass ich nicht nur die Stellung des Schachbretts verändern muss, sondern auch x-pos und y-pos der Figuren aktualisieren muss.
😡😡😡😡
Klar, dass die beim Repaint dann alle noch an der alten Position stehen.

Zu kompliziert gedacht 🙁
Sorry fürs Generve
 

Neue Themen


Zurück
Oben