Swing Verhindern, dass repaint() kaskadiert

I3LacKFuSIoN

Mitglied
Hallo zusammen,

ich bin gerade dabei ein Programm, welches Labyrinths generieren und lösen kann ein GUI zu erstellen.
(Hierzu nutze ich die neuste Eclipse Version)
Es lief bisher alles so wie ich es mir vorgestellt habe, jedoch bin ich jetzt auf ein Problem gestossen:

Ich möchte die Ausgabe bzw. den Lösungsweg Schrittweise darstellen und will in einem JPane für jeden gegangenen Schritt das Labyrinth aktualisieren. (Der Delay zwischen den Schritten soll über einen Slider verstellbar sein, ist aber Nebensache)
Bislang habe ich es hinbekommen, dass das Programm zwar den Weg schritweise erstellt, jedoch scheint es, als würden die repaint()-Anfragen aufgestaut, bis die Schleife, mit der ich die Schritte bestimmen und ausgeben will, vollständig durchlaufen wurde. Dadurch werden die Delays zu einem einzelnen langem und die gesamte schrittweise Ausgabe geschieht nicht schrittweise, sondern auf einmal.

Ich habe bereits ein wenig im Internet recherchiert und ein paar Dinge ausprobiert.
1. Ich anstelle von repaint() paintImmediatly() ausprobiert.
2. Ich habe verschiedene Wege getestet um den Delay umzusetzen (u.a. Einen Swing-Timer und einen selbstgebastelten), da ich zuerst dachte es hängt damit zusammen.
3. Ich habe einen Freund um Rat gefragt, jedoch sagte er mir, ich könne das Problem nicht über einen seperaten thread für das repaint() lösen, weil man in einer GUI nur einen thread nutzen könne.


Dies ist die Code, mit dem ich den Weg ermittle und entsprechend einfügen will:

Java:
do {
            changes = false;
            zufallszahl = (int)((Math.random()) * 4 + 1);
            //Bestimmen, welches benachbarte Feld geprüft wird
    switch (zufallszahl) {
        case 1:
                if(Feld[aktuelleSpalte][aktuelleZeile-1].contentEquals("Z"))
            {
                Feld[aktuelleSpalte][aktuelleZeile] = ".";
                paintWay[aktuelleSpalte][aktuelleZeile] = ".";
                aktuelleZeile = aktuelleZeile-1;
                weg = weg + "UP\n";
                changes=true;
                schritte++;
            }else {
            if(Feld[aktuelleSpalte][aktuelleZeile-1].contentEquals(" "))
            {
                if(Feld[aktuelleSpalte][aktuelleZeile].contentEquals("S"))
                {
                    aktuelleZeile = aktuelleZeile-1;
                    weg = weg + "UP\n";
                    changes=true;
                    schritte++;
                }else {
                Feld[aktuelleSpalte][aktuelleZeile] = ".";
                paintWay[aktuelleSpalte][aktuelleZeile] = ".";
                aktuelleZeile = aktuelleZeile-1;
                weg = weg + "UP\n";
                changes=true;
                schritte++;
            }
            }
            }
            break;
        case 2:
                if(Feld[aktuelleSpalte+1][aktuelleZeile].contentEquals("Z"))
            {
                Feld[aktuelleSpalte][aktuelleZeile] = ".";
                paintWay[aktuelleSpalte][aktuelleZeile] = ".";
                aktuelleSpalte = aktuelleSpalte +1;
                weg = weg + "RIGHT\n";
                changes=true;
                schritte++;
            }else {
            if(Feld[aktuelleSpalte+1][aktuelleZeile].contentEquals(" "))
            {
                if(Feld[aktuelleSpalte][aktuelleZeile].contentEquals("S"))
                {
                    aktuelleSpalte = aktuelleSpalte+1;
                    weg = weg + "RIGHT\n";
                    changes=true;
                    schritte++;
                }else {
                Feld[aktuelleSpalte][aktuelleZeile] = ".";
                paintWay[aktuelleSpalte][aktuelleZeile] = ".";
                aktuelleSpalte = aktuelleSpalte+1;
                weg = weg + "RIGHT\n";
                changes=true;
                schritte++;
            }
            }
            }
            break;
        case 3:
                if(Feld[aktuelleSpalte][aktuelleZeile+1].contentEquals("Z"))
            {
                Feld[aktuelleSpalte][aktuelleZeile] = ".";
                paintWay[aktuelleSpalte][aktuelleZeile] = ".";
                aktuelleZeile = aktuelleZeile +1;
                weg = weg + "DOWN\n";
                changes=true;
                schritte++;
            }else {
            if(Feld[aktuelleSpalte][aktuelleZeile+1].contentEquals(" "))
            {
                if(Feld[aktuelleSpalte][aktuelleZeile].contentEquals("S"))
                {
                    aktuelleZeile = aktuelleZeile+1;
                    weg = weg + "DOWN\n";
                    changes=true;
                    schritte++;
                }else {
                Feld[aktuelleSpalte][aktuelleZeile] = ".";
                paintWay[aktuelleSpalte][aktuelleZeile] = ".";
                aktuelleZeile = aktuelleZeile+1;
                weg = weg + "DOWN\n";
                changes=true;
                schritte++;
            }
            }
            }
            break;
        case 4:
                if(Feld[aktuelleSpalte-1][aktuelleZeile].contentEquals("Z"))
            {
                Feld[aktuelleSpalte][aktuelleZeile] = ".";
                paintWay[aktuelleSpalte][aktuelleZeile] = ".";
                aktuelleSpalte = aktuelleSpalte -1;
                weg = weg + "LEFT\n";
                changes=true;
                schritte++;
            }else {
            if(Feld[aktuelleSpalte-1][aktuelleZeile].contentEquals(" "))
            {
                if(Feld[aktuelleSpalte][aktuelleZeile].contentEquals("S"))
                {
                    aktuelleSpalte = aktuelleSpalte-1;
                    weg = weg + "LEFT\n";
                    changes=true;
                    schritte++;
                }else {
                Feld[aktuelleSpalte][aktuelleZeile] = ".";
                paintWay[aktuelleSpalte][aktuelleZeile] = ".";
                aktuelleSpalte = aktuelleSpalte-1;
                weg = weg + "LEFT\n";
                changes=true;
                schritte++;
            }
            }
            }
            break;
        default:
            break;
        }
    //Ende Feldüberprüfung, wenn es frei ist wird der Weg aktualisiert
      
    if(changes==true) { 
      
        try {
            Thread.sleep(slider.getValue()*1000);
        } catch (InterruptedException e) {
           JOptionPane.showInternalMessageDialog(null, "ERROR");
      }
      
      
      
        spaltenZaehler = 0;
        zeilenZaehler = 0;
      
      
        do {
            do {
                generatedMaze = generatedMaze + (paintWay[spaltenZaehler] [zeilenZaehler] + "");
                spaltenZaehler++;
            }while(spaltenZaehler<paintWay.length);
            zeilenZaehler++;
            generatedMaze = generatedMaze + "\n";
            spaltenZaehler = 0;
        }while(zeilenZaehler<paintWay[1].length);
      
        System.out.println("log1");

        textOutputMaze.repaint();
  
      
        }
    //Wenn sich etwas aktualisiert hat sollte mit der If-Abfrage dafür gesorgt werden, dass das JPane verzögert aktualisiert wird
            }while(!Feld[aktuelleSpalte][aktuelleZeile].contentEquals("Z"));

//Ende Wegsuche

PS: Bin Java-Anfänger, daher entschuldigt bitte den "gepfuschten" Code
 
Zuletzt bearbeitet:

Thallius

Top Contributor
Du kannst nicht im Main-Thread etwas tun und gleichzeitig erwarten, dass sich die UI aktualisiert. Der Begriff nach dem Du suchen solltest ist SwingWorker.

Gruß

Claus
 
K

kneitzel

Gast
Ja, ich erwarte auch, dass er da im UI Thread etwas macht und dann mit irgendwelchen Aufrufen das neumalen erzwingen will.

Ich habe einmal ein Spiel geschrieben in Java und da habe ich dann die Problematik zweigeteilt:
a) Das eigentliche Spiel lief in einem eigenen Thread. Da konnte dann die Spielereingabe verarbeitet und auch die Serverkommunikation stattfinden. Ergebnis war da dann einfach ein Bild, welches regelmäßig neu gemalt wurde und der GUI zur Verfügung gestellt wurde.
b) Die GUI war relativ dumm. Eingaben vom Spieler wurden an den Spiel-Thread gereicht (Einfache synchronized Queue reicht da am Anfang auf jeden Fall). Und die GUI hat neue Bilder entgegen genommen um diese dann darzustellen (also da wurde dann ein repaint ausgelöst, sprich: Der UI wurde gesagt: mal dich selbst.

Wenn man das einmal angeht, dann kommt man recht schnell auf einige Themen, wie z.B.:
- Wiederbenutzung der "Bilder". Ich hatte dann unter dem Strich 3 Bilder: 1 Bild wurde aktiv von der UI gezeigt, 1 Bild wartete darauf, als nächstes gezeichnet zu werden oder stand zur Wiederverwendung zur Verfügung und 1 Bild wurde gerade aktualisiert.
- Synchronisierung mehrere Threads und kleinere Optimierungen, damit nicht mehr CPU verballert wurde als unbedingt notwendig.

Das wäre so das, was ich ggf. anraten würde. Vielleicht ist es hilfreich, aber noch gab es ja nicht genug Informationen bezüglich dem, was er genau macht.
 

mihe7

Top Contributor
Ich habe einen Freund um Rat gefragt, jedoch sagte er mir, ich könne das Problem nicht über einen seperaten thread für das repaint() lösen, weil man in einer GUI nur einen thread nutzen könne.
Nicht ganz richtig, aber im Ergebnis OK :)

Alles, was im UI passiert läuft unter Swing im sog. Event Dispatch Thread. Im Prinzip arbeitet dieser eine Warteschlange mit Aufträgen (Ereignissen) ab, die sog. Event Queue.

Wenn Du ein repaint() ausführst, wird ein entsprechender Auftrag in die Event Queue gelegt und zu einem späteren Zeitpunkt, wenn der Event Dispatch Thread den Auftrag aus der Queue verarbeitet, findet dann das Neuzeichnen statt. Dabei können auch mehrere repaint-Ereignisse zu einem zusammengefasst werden.

Blockierst Du nun den EDT, aktualisiert sich das UI natürlich auch nicht mehr, weil die Queue während der Blockade nicht mehr abgearbeitet wird. Was Du also brauchst ist ein separater Thread, um den EDT nicht zu blockieren. Gleichzeitig muss dieser Thread dafür sorgen, dass Änderungen am GUI nur im EDT ausgeführt werden. Dazu gibt es die Möglichkeiten, einen Auftrag aus anderen Threads heraus in die Event Queue zu legen (invokeLater-Methode von EventQueue bzw. SwingUtilities).

Womit Du den separaten Thread realisierst, bleibt Dir überlassen: das kann direkt ein Thread sein, aber auch ein Timer oder SwingWorker usw.
 

mrBrown

Super-Moderator
Mitarbeiter
Du kannst nicht im Main-Thread etwas tun und gleichzeitig erwarten, dass sich die UI aktualisiert. Der Begriff nach dem Du suchen solltest ist SwingWorker.
Wobei du hier mit "Main-Thread", anders als üblich nicht den Thread namens "main" meinst, sondern den EDT, grad bei diesem Thema ein relevanter Unterschied.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
richis-fragen Swing Verhindern, dass die VerticalScrollbar hüpft bei Pfeilup/-down tastendruck AWT, Swing, JavaFX & SWT 2
K JavaFX CSS Border (Verschiebung verhindern) AWT, Swing, JavaFX & SWT 4
S Swing Deselektion in JTable verhindern AWT, Swing, JavaFX & SWT 0
Thallius Swing "..." beim JLabel verhindern? AWT, Swing, JavaFX & SWT 3
Neumi5694 Event Handling ListSelectionEvents verhindern AWT, Swing, JavaFX & SWT 0
Neumi5694 Swing Gridbaglayout - automatische Anpassung verhindern AWT, Swing, JavaFX & SWT 1
I Monitor-Standyby verhindern AWT, Swing, JavaFX & SWT 6
V automatisches neuzeichnen verhindern AWT, Swing, JavaFX & SWT 3
J jFrame verschieben verhindern AWT, Swing, JavaFX & SWT 4
E SWT Popupmenu auf der Überschrift eines swt.widgets.Table verhindern? AWT, Swing, JavaFX & SWT 3
lumo SWT ScrolledComposite MouseWheel verhindern AWT, Swing, JavaFX & SWT 3
H minimieren verhindern AWT, Swing, JavaFX & SWT 4
L Swing setVisible(false) bei GridBagLayout - wie Layoutverschiebung verhindern? AWT, Swing, JavaFX & SWT 2
D Swing Dialog schließen verhindern bei Fehleingabe AWT, Swing, JavaFX & SWT 2
Developer_X Swing JTextArea verhindern von Tab AWT, Swing, JavaFX & SWT 2
DeeDee0815 AWT Flimmern verhindern AWT, Swing, JavaFX & SWT 4
S Swing Dynamische JPanels: Vertikales Strecken verhindern AWT, Swing, JavaFX & SWT 4
R Verhindern das Inhalt in JScrollPane breiter ist als JScrollPane..? AWT, Swing, JavaFX & SWT 10
C Swing Andocken einer ToolBar verhindern AWT, Swing, JavaFX & SWT 3
A Fenster maximieren (oben rechts) verhindern AWT, Swing, JavaFX & SWT 3
T Verhindern der überlagerung von JComponenten AWT, Swing, JavaFX & SWT 8
G Verhindern, das AbstractAction Text und Icons überschreibt? AWT, Swing, JavaFX & SWT 3
M ScreenUpdate verhindern AWT, Swing, JavaFX & SWT 6
T Minimieren und Maximieren eines JFrames verhindern AWT, Swing, JavaFX & SWT 9
D Sortierung beim Klicken auf Header einer JdbTable verhindern AWT, Swing, JavaFX & SWT 3
I jScrollpane: Scrollverschiebung durch Pfeiltasten verhindern AWT, Swing, JavaFX & SWT 2
M JCheckbox, das selektieren verhindern AWT, Swing, JavaFX & SWT 9
D JTable Spaltenauswahl verhindern AWT, Swing, JavaFX & SWT 3
U Flackern verhindern AWT, Swing, JavaFX & SWT 5
G JEditorPane Zeilenumbruch verhindern AWT, Swing, JavaFX & SWT 2
A JScrollPane Scrollleisten verhindern AWT, Swing, JavaFX & SWT 2
A JFileChooser verhindern von allFiles option AWT, Swing, JavaFX & SWT 2
G Verhindern von automatischen Zeilenum. in JTextPane AWT, Swing, JavaFX & SWT 2
B paint - Überlagerung verhindern AWT, Swing, JavaFX & SWT 3
S verhindern von drag-n-drop von swing componenten AWT, Swing, JavaFX & SWT 2
M JTextPane - Zeilenumbruch verhindern stoppen deaktivieren :) AWT, Swing, JavaFX & SWT 5
S DOS-Fenster verhindern AWT, Swing, JavaFX & SWT 2
P JInternalFrame: Verhindern das man es verschieben kann AWT, Swing, JavaFX & SWT 2
G JList: Anzeige von null-Werten verhindern AWT, Swing, JavaFX & SWT 3
M JTree: zusammenklappen verhindern AWT, Swing, JavaFX & SWT 3
D Schließen eines Fensters verhindern AWT, Swing, JavaFX & SWT 3
_user_q [JavaFX] Spinner so einstellen, dass er nicht leer bleiben darf? AWT, Swing, JavaFX & SWT 6
C Bilder so einbinden, dass sie sich ändern AWT, Swing, JavaFX & SWT 6
T JavaFX Dialog schließt ohne dass es schließen soll AWT, Swing, JavaFX & SWT 1
S Kann man erzwingen, dass Java 'zu Ende zeichnet'..? AWT, Swing, JavaFX & SWT 7
A Swing Funktionsaufruf sorgt dafür, dass Fenster sich aufhängt AWT, Swing, JavaFX & SWT 2
X Swing Wie merken Buttons, dass sie aus dem Bild sind ? AWT, Swing, JavaFX & SWT 4
aze JTextfield nur so breit dass alle zeichen sichtbar sind AWT, Swing, JavaFX & SWT 2
aze JDialog immer so breit ,dass die Überschrift sichtbar ist AWT, Swing, JavaFX & SWT 6
S Table oder TableModel so ueberschreiben, dass Columns minimale Breite haben? AWT, Swing, JavaFX & SWT 2
J Im JLabel Bild durch anderes ersetzen, ohne dass es 'blinkt' AWT, Swing, JavaFX & SWT 12
M sicherstellen, dass nur eine Instanz läuft. AWT, Swing, JavaFX & SWT 6
D Repaint Funktioniert nicht AWT, Swing, JavaFX & SWT 2
D JUNG Repaint function does not work AWT, Swing, JavaFX & SWT 2
E repaint Probleme AWT, Swing, JavaFX & SWT 13
G listener repaint() - verschiedene Darstellung AWT, Swing, JavaFX & SWT 24
ExceptionOfExpectation Textdarstellung auf einem Canvas mit Hilfe von repaint(); AWT, Swing, JavaFX & SWT 6
J actionperformed wird nicht aufgerufen/ repaint() AWT, Swing, JavaFX & SWT 6
L Swing repaint() ruft paintComponent(g1d) nicht auf AWT, Swing, JavaFX & SWT 12
G Repaint wird nicht durchgeführt AWT, Swing, JavaFX & SWT 8
ms_cikar Update swingUtilities Repaint in der Schleife AWT, Swing, JavaFX & SWT 3
T Swing Probleme mit repaint() bzw. JScrollPane AWT, Swing, JavaFX & SWT 7
N Swing JButtons werden nach repaint() doppelt dargestellt AWT, Swing, JavaFX & SWT 12
K Methode repaint() AWT, Swing, JavaFX & SWT 1
B Swing Wann brauche ich repaint() ? AWT, Swing, JavaFX & SWT 1
javampir Swing repaint in JavaFX Anwendung AWT, Swing, JavaFX & SWT 3
A repaint(); AWT, Swing, JavaFX & SWT 9
J Swing ungewünschter Nebeneffekt bei der repaint() Methode AWT, Swing, JavaFX & SWT 3
A Problem: repaint() - Schleife AWT, Swing, JavaFX & SWT 3
S 2D-Grafik repaint()-Aufruf. Und nichts geschieht. AWT, Swing, JavaFX & SWT 5
Joew0815 JDialog repaint() funktioniert nicht wie gewünscht. AWT, Swing, JavaFX & SWT 2
P JPanel und Repaint AWT, Swing, JavaFX & SWT 5
J JavaFX Automatisches Neuzeichnen ("Repaint") abstellen. AWT, Swing, JavaFX & SWT 10
F JTable Repaint Issue AWT, Swing, JavaFX & SWT 1
N Observer: update ruft nicht repaint auf AWT, Swing, JavaFX & SWT 0
C Repaint() funktioniert nicht in TabbedPanel AWT, Swing, JavaFX & SWT 5
S JList repaint AWT, Swing, JavaFX & SWT 1
L NullpointerException und Probleme mit repaint() AWT, Swing, JavaFX & SWT 11
M Repaint mittels Button richtig aufrufen klappt nicht AWT, Swing, JavaFX & SWT 1
B Repaint auf JFrame, JLabel und ImageIcon AWT, Swing, JavaFX & SWT 4
K 2D-Grafik Paint - Wie binde ich repaint ein? AWT, Swing, JavaFX & SWT 8
D repaint() klappt anders als vorgestellt AWT, Swing, JavaFX & SWT 15
R Repaint() in Schleifen, Threads AWT, Swing, JavaFX & SWT 13
B Swing Repaint Problem - mal wieder AWT, Swing, JavaFX & SWT 5
P 2D-Grafik Gezielter Repaint einzelner Frames in Java-Game AWT, Swing, JavaFX & SWT 6
javampir Bei repaint nix los AWT, Swing, JavaFX & SWT 2
B Swing repaint() AWT, Swing, JavaFX & SWT 3
Ernesto95 AnimationLoop - Problem bei Aufruf von repaint AWT, Swing, JavaFX & SWT 6
P 2D-Grafik repaint(); steigender RAM Verbauch AWT, Swing, JavaFX & SWT 6
Y KeyListener, GUI Thread, repaint AWT, Swing, JavaFX & SWT 7
S Applet Repaint AWT, Swing, JavaFX & SWT 3
M Programm hängt sich auf nachdem repaint() benutzt wurde AWT, Swing, JavaFX & SWT 2
R Swing Grafikfehler bei repaint AWT, Swing, JavaFX & SWT 2
N repaint() blockieren AWT, Swing, JavaFX & SWT 6
K canvas zeig nach repaint nichts an AWT, Swing, JavaFX & SWT 8
M Repaint() AWT, Swing, JavaFX & SWT 14
J Swing repaint, repaint, repaint AWT, Swing, JavaFX & SWT 8
M Applet repaint() verlangsamen AWT, Swing, JavaFX & SWT 7
R paintComponent malt bei repaint() Rahmen um Panel AWT, Swing, JavaFX & SWT 7
P EDT Problem? Kein Aufruf der repaint Methode AWT, Swing, JavaFX & SWT 6

Ähnliche Java Themen

Neue Themen


Oben