Verspätete Anzeige in Textfeldern

kodela

Bekanntes Mitglied
Hallo,

ich arbeite an einem Schachprogramm und habe folgendes Problem:

Wird vom Anwender ein gültiger Zug eingegeben, dann soll dieser Zug, einschließlich der dafür benötigten Denkzeit, im Info-Bereich ausgegeben werden. Außerdem soll in diesem Bereich die Farbe der nun am Zug befindlichen Seite angezeigt werden. Im Anschluss daran soll das Programm einen Gegenzug suchen und ausführen, es sei denn, die Gegenzugsuche ist explizit ausgeschlossen.

Aus mir unerklärlichen Gründen werden die genannten Infos jedoch nicht unmittelbar nach der Eingabe eines Zuges angezeigt, sondern erst nach Abschluss der Gegenzugsuche. Ausgegeben wird jedoch der Zug selbst, also der Wechsel einer Figur von einem zu einem anderen Feld.

Der Anzeigebereich der Anwendung ist zweigeteilt, einmal ein JPanel für das Schachfeld und eines für das Infofeld. Im Infofeld sind eine Reihe von JTextfields für die diversen Anzeigen.

Hier ein kommentierter Code-Auszug der betroffenen Methoden:
Java:
Class InOut:

    private void movePiece(int i) {
        int color = board.Display[i].color;                         // Farbe der Figur
        if (board.Display[i].piece == 0) {                          // keine Figur, zweiter Klick
            color = -1;                                             // dann leeres Zielfeld
        }
        if ((lastFild.piece > 0)                                    // bereits Figur markiert
                && (talk.Player != color)) {                        // keine eigene Figur angeklickt
            if (talk.MoveCheck(lastIndex, i)) {                     // Zug prüfen, falls erfolgreich
           
// Bei korrektem Zug ist nun bereits die Anzeige des Zuges und des nächsten Players veranlasst.
// Diese Infos werden jedoch noch nicht angezeigt.

                if (cApp.Level < L_twoplayer) {                     // Level mit Zugsuche
                    talk.startMove();                               // Zugsuche einleiten
                }
            } else {                                                // Zug ist ungültig
                PrintPiece(                                         // also Markierung entfernen
                        lastIndex, lastFild.piece, lastFild.color);
            }
        }
        resetInput();                                               // zurücksetzen für nächsten Zug
    }

   
Class Talk:

// Nach dem Aufruf von talk.MoveCheck() wird bei einem gültigen Zug diese Methode aufgerufen.

    void enterMove(MOT move) {
        disp.PrintMove(MoveNo, Player,           // >> Zug im Infofenster ausgeben <<
                move, tm.getTotalTime(Player));
        MakeMove(move);                                             // Zug formal ausführen
        board.UpdateBoard();                                        // Brett neu ausgeben
        cApp.showColorToPlay(Player);            // >> Ziehenden im Info-Fenster <<
        PrintComment();                                             // ev. erf. Meldung ausgeben
    }
   
// Die Anzeige des Zuges, einschließlich der dafür benötigten Zeit erfolgt über die Klasse Display.
// Die Anzeige des nun am Zug befindlichen Spielers direkt über die Hauptklasse ChessApp.
// Anschließend erfolgt der Rücksprung  zu Methode InOut.movePiece().  Die veranlassten Infos
// werden, wenn jetzt durch den Aufruf von talk.StartMove() die Suche eines Gegenzuges eingeleitet
// wird, noch nicht ausgegeben. Sie erfolgt jedoch, wenn auf Grund der Leveleinstellung der Aufruf
// von talk.StartMove() übersprungen wird.


Class Display:

// Der Vollständigkeit halber hier noch die Methode PrintMove() für die Ausgabe des Zuges.

    public void PrintMove(int moveno, int color, MOT move, int time) {
        printThinkTime(color, time);                                // Zeit ausgeben
        String sMove = "" + (moveno/2+1) + "." + MoveStr(move);        // String für den Zug bilden
        if (color == WHITE) {                                        // für Weiß?
            cApp.tfLastMoveWhite.setText(sMove);                    // dann in Feld für Weiß
        } else {
            cApp.tfLastMoveBlack.setText(sMove);                    // sonst in Feld für Schwarz
        }
    }
Ich habe es schon mit einem Aufruf von repaint() (cApp.repaint() / cApp.infoPain.repaint()) an unterschiedlichen Stellen versucht, leider jedoch ohne Erfolg.

Hat jemand eine Idee, warum der Aufruf von talk.startMove() die sofortige Anzeige der Infos verhindert?

Danke schon einmal für jede Antwort.

Gruß, kodela
 

LimDul

Top Contributor
In Swing gibt es einen Thread (den Event Dispatching Thread), der für alles verantwortlich ist - abarbeiten der Events, Zeichnen etc.

Das heißt, so lange in in Code, der z.B. aus einem ActionListener aufgerufen wird, bist, ist die gesamte Gui blockiert. Erst wenn das abgearbeitet ist, geht es weiter. Deswegen darf man in diesem Code nie folgende Dinge tun:
* Thread.sleep
* Sonstige langlaufende Aktionen

Wenn man sowas tun will, muss man das in eigene Threads auslagern (Die dürfen dann aber keine Gui-Element direkt manipulieren, sondern nur mittels SwingUtils.invokeAndWait bzw. invokeLater)
 

kodela

Bekanntes Mitglied
Danke für die Antwort!

Ich habe mittlerweile festgestellt, dass mein Problem am MouseListener liegt, von dem aus myMouseClicked() und weiter dann movePiece() aufgerufen wird. Erst wenn von dort der Rücksprung erfolgt, wird der aufgerufene MouseListener verlassen und damit die Anzeige freigegeben.

Was müsste ich tun, dass diese Blockierung umgangen werden kann? Durch die Aufrufe von talk.MoveCheck und talk.startMove(); wird auf weitere Klassen (Search und Evalu) zugegriffen. Die kann ich ja nicht alle in eigene Threads legen, oder doch?

Warum wird dann aber die Figur gezogen?
 

LimDul

Top Contributor
Danke für die Antwort!

Ich habe mittlerweile festgestellt, dass mein Problem am MouseListener liegt, von dem aus myMouseClicked() und weiter dann movePiece() aufgerufen wird. Erst wenn von dort der Rücksprung erfolgt, wird der aufgerufene MouseListener verlassen und damit die Anzeige freigegeben.

Was müsste ich tun, dass diese Blockierung umgangen werden kann? Durch die Aufrufe von talk.MoveCheck und talk.startMove(); wird auf weitere Klassen (Search und Evalu) zugegriffen. Die kann ich ja nicht alle in eigene Threads legen, oder doch?

Warum wird dann aber die Figur gezogen?
Natürlich, du kannst ja die Objekte mit übergeben beim erzeugen des Threads.
 

kodela

Bekanntes Mitglied
Ich habe jetzt die Search-Klasse in einen eigenen Threas gepackt, was sowieso geplant war. Trotzdem bekomme ich die Infos zum Zug, für den in Search der Gegenzug gesucht wird, nicht angezeigt.

Was ich einfach nicht verstehe ist, dass der Zug selbst auf dem Brett angezeigt wird, die Infos dagegen nicht. Irgendwie sind bei mir da die Weichen für meine Gedankengänge falsch gestellt.
 

mihe7

Top Contributor
Ohne Code kann man da nicht viel sagen, außer, dass die Updates im EDT stattfinden müssen. D. h. wenn Du z. B. in einem separaten Thread das GUI aktualisieren willst, musst Du invokerLater verwenden.
 

kodela

Bekanntes Mitglied
Ja, das ist mir schon klar, dass es ohne den ganzen Code zu kennen, schwierig ist, dazu etwas zu sagen. Andererseits ist es nahezu unmöglich, hier den gesamten Code zu zeigen, der im Zusammenhang mit meinem Problem ausgeführt wird. Deshalb habe ich mich in meinem ersten Beitrag bemüht, die wichtigsten Codeteile zu zeigen. Ich will aber versuchen, Grundzüge des Projekts und in besonderem Maße die problemrelevanten Teile kurz darzustellen:

Zur Zeit besteht das Projekt aus zwanzig Klassen. Die Hauptklasse ist "ChessApp" mit der main-Methode:

Code:
    public static void main(final String args[]) {
        try {
            UIManager.setLookAndFeel(
                    UIManager.getSystemLookAndFeelClassName());
        } catch (ClassNotFoundException
                | InstantiationException
                | IllegalAccessException
                | UnsupportedLookAndFeelException ex) {
            JOptionPane.showMessageDialog(null,
                    "Folgender Fehler ist aufgetreten: \n\n"
                    + ex.getMessage(),
                    "Hinweis", 1);
        }
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new ChessApp(args).setVisible(true);
            }
        });
    }
In ChessApp wird auch die GUI erstellt und verwaltet. Sie dient ferner als Schnittstelle für die meisten Klassen. Die GUI selbst verfügt neben den Menü-, Symbol- und Statusleisten über die beiden Panele für das Schachbrett und die Info-Anzeige.

Die Klasse InOut ist für alle Ein- und Ausgaben im Bereich des Schachbrettes zuständig. Die Ausgabe umfasst einerseits die Darstellung des Schachbrettes mit seinen Figuren. Die Eingabe erfolgt ausschließlich über die Maustaste und bezieht sich ausschließlich auf das Ziehen der Figuren. Dafür wird bisher noch erst ein Startfeld mit einer Figur markiert und dann das Zielfeld. Später soll eine Figur auch erfasst und auf dem Zielfeld abgesetzt werden können.

Führt der Anwender einen Zug aus, wird dieser über den Aufruf von MoveCheck() geprüft, ob er ausführbar ist. MoveCheck() aus der Klasse Talk greift dafür auf die Klasse MovGen zurück. Falls der Zug nicht ausführbar ist, muss die Markierung des Startfeldes entfernt werden. Andernfalls wird die Figur aus dem Startfeld zu entfernt und auf das Zielfeld gesetzt. Dies geschieht von der Methode enterMove() der Klasse Talk, welche von MoveCheck() nach erfolgreicher Prüfung abschließend aufgerufen wird. enterMove() habe ich in meinem ersten Beitrag bereits gezeigt.

Das Eigenartige für mich ist nun, dass in enterMove() einmal die Zugbeschreibung und die Farbe des nächst Ziehenden ausgegeben sowie durch den Aufruf von UpdateBorad() der Klasse Board() über die Methode PrintPiece() der Klasse InOut die Figur auf ihre neue Position gesetzt, aber nur letzteres auch sofort angezeigt wird.

Bis hierher gäbe es noch kein Problem, aber nun, wenn der Zug ausführbar ist, muss der Gegenzug gesucht werden und das kostet Zeit, eventuell je nach Leveleinstellung sogar sehr viel Zeit, in der über die GUI nichts angezeigt wird, weder der bereits getätigte Zug, noch die Informationen zur Zugsuche, also die laufende "Denkzeit", die Tiefe der Suche und die bisher beste gefundene Zugfolge.

Wie kann man nach dem Aufruf einer Methode die aufrufende Methode beenden, ohne ein Ergebnis abzuwarten? Wenn mir das gelingen würde, könnte ich ja von MoveCheck() aus alle in InOut erforderlichen Aufräumarbeiten vornehmen.
 

mihe7

Top Contributor
Andererseits ist es nahezu unmöglich, hier den gesamten Code zu zeigen, der im Zusammenhang mit meinem Problem ausgeführt wird.
Das Problem ist, dass man nicht sieht, was in welchem Thread ausgeführt wird.

Bis hierher gäbe es noch kein Problem, aber nun, wenn der Zug ausführbar ist, muss der Gegenzug gesucht werden und das kostet Zeit, eventuell je nach Leveleinstellung sogar sehr viel Zeit, in der über die GUI nichts angezeigt wird, weder der bereits getätigte Zug, noch die Informationen zur Zugsuche, also die laufende "Denkzeit", die Tiefe der Suche und die bisher beste gefundene Zugfolge.
Mal ausgehend davon, dass das alles im EDT ausgeführt wird (z. B. als Reaktion auf einen Mausklick), wäre die Suche nach dem Gegenzug in einem separaten Thread auszuführen. Die anzuzeigenden Informationen, die von dieser Suche abhängen, müssten dann am Ende des Threads aktualisiert werden, dazu wird das invokeLater verwendet.

Mal ein Beispiel:
Java:
import java.awt.BorderLayout;
import javax.swing.*;

public class Test {
    JLabel status = new JLabel(" ");
    JLabel message = new JLabel(" ");
    JButton button = new JButton("Klick mich");

    private void reset() {
        status.setText("Döse vor mich hin");
        message.setText(" ");
        button.setEnabled(true);
    }

    public void run() {
        reset();

        button.addActionListener(e -> machWas());

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.add(status, BorderLayout.SOUTH);

        frame.add(button, BorderLayout.NORTH);
        frame.add(message);
        frame.setSize(800, 600);
        frame.setVisible(true);
    }

    private void machWas() {
        // wird im EDT ausgeführt
        button.setEnabled(false);
        status.setText("Arbeite...");
        Thread th = new Thread(() -> schwereArbeit());

        th.start();
        // Methode wird sofort beendet
    }

    private void schwereArbeit() {
        // schwere Arbeit im separaten Thread
        try {
            for (int i = 0, n = 10; i < n; i++) {
                Thread.sleep(200);

                // UI-Update im EDT
                int step = i+1;
                SwingUtilities.invokeLater(() -> {
                    message.setText(String.format("Schritt %d von %d",
                           step, n));
                });
            }
        } catch (InterruptedException ex) {
            // ignore
        } finally {
            // in jeden Fall UI wieder zurücksetzen
            SwingUtilities.invokeLater(() -> {
                reset();
            });
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new Test().run());
    }
}
 

kodela

Bekanntes Mitglied
Danke für das Beispiel!

Ich habe es mir bereits genauer angesehen. Mal sehen, was und wie ich daraus etwas für mein Projekt nutzen kann. Fest steht, dass ich mein ganzes Konzept in Frage stellen muss, denn während der Suche erfolgt nicht nur keine Ausgabe für die GUI, auch die Timerklasse, über die ja bestimmt wird, wann die zulässige Suchzeit beendet ist, arbeitet erst wieder, wenn die in InOut angestoßene Suche beendet ist. Während der Zugsuche für das Programm habe ich also mindestens drei weitere Threads, die gleichzeitig aktiv sind, oder es sein sollten, die GUI, den MouseAdapter und den Timer.

Mal sehen, was mir da einfällt.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
hannibalstgt Fehler bei JCOMBOBOX GUI Anzeige AWT, Swing, JavaFX & SWT 4
M suche geeignetes Fenster zur Anzeige AWT, Swing, JavaFX & SWT 49
G Problem mit der Anzeige von jLabel. Unlesbar wenn der Text geändert wird. AWT, Swing, JavaFX & SWT 28
S AffineTranformation Bilder verschwinden von Anzeige bei Pan, Zoom AWT, Swing, JavaFX & SWT 6
kodela Swing Anzeige des Warten-Cursors AWT, Swing, JavaFX & SWT 8
F BorderLayout Hilfe bei Anzeige AWT, Swing, JavaFX & SWT 2
L Java FX Keine Anzeige Im Tableview AWT, Swing, JavaFX & SWT 4
F JScrollPane anzeige AWT, Swing, JavaFX & SWT 7
F Design-Anzeige im Windowbuilder AWT, Swing, JavaFX & SWT 3
thet1983 JavaFX TableView Objekt Daten anzeige AWT, Swing, JavaFX & SWT 2
D JavaFX Control zur Anzeige von eBooks AWT, Swing, JavaFX & SWT 5
javampir Swing Anzeige der FileFilter im JFileChooser AWT, Swing, JavaFX & SWT 0
T Probleme mit Anzeige von Elementen im JPanel AWT, Swing, JavaFX & SWT 1
J JavaFX JavaFX Probleme bei der Anzeige von Text AWT, Swing, JavaFX & SWT 18
G JScrollPane bricht am Ende der Anzeige nicht um AWT, Swing, JavaFX & SWT 2
V JWindow: Falsche Anzeige auf Ubuntu AWT, Swing, JavaFX & SWT 2
N JDialog als Progress-Anzeige AWT, Swing, JavaFX & SWT 6
M AWT Gui anzeige Probes - Elemente erscheinen nicht regelmäßig AWT, Swing, JavaFX & SWT 2
A JFreeChart BarChart invertierte anzeige oder werte bereich von-bis AWT, Swing, JavaFX & SWT 4
Ollek JList - neuer Eintrag in ArrayList dadurch keine Anzeige der Objekte AWT, Swing, JavaFX & SWT 18
P Swing Problem mit der Anzeige AWT, Swing, JavaFX & SWT 12
B SWT TreeViewer dynamische Anzeige von Icons AWT, Swing, JavaFX & SWT 3
M Anzeige updatet sich erst am Ende des Programms AWT, Swing, JavaFX & SWT 3
J JList, Anzeige aktualisieren AWT, Swing, JavaFX & SWT 7
J Kleines Anzeige Problem(nur blanker Frame) AWT, Swing, JavaFX & SWT 22
A Swing JFileChooser - Anzeige in Echtzeit filtern AWT, Swing, JavaFX & SWT 10
N Swing JTextPane zur Anzeige von HTML AWT, Swing, JavaFX & SWT 2
A Swing Anzeige Text in JScrollpane AWT, Swing, JavaFX & SWT 8
M TabbpedPane Anzeige aktualisieren AWT, Swing, JavaFX & SWT 6
S Anzeige von Beschleunigungswerten AWT, Swing, JavaFX & SWT 2
S Anzeige eines JWindows AWT, Swing, JavaFX & SWT 3
N jcomboBox anderer Wert als Anzeige AWT, Swing, JavaFX & SWT 6
B Swing Java crashed nach Anzeige JOptionePane AWT, Swing, JavaFX & SWT 20
S Probleme mit Anzeige von JComboBox AWT, Swing, JavaFX & SWT 2
J Anzeige AWT, Swing, JavaFX & SWT 5
F Verzögerung bei der ersten Anzeige AWT, Swing, JavaFX & SWT 6
timbeau Gitter in Sudoko-Anzeige AWT, Swing, JavaFX & SWT 9
J Swing JTable, eigener TableCellRenderer Keine Anzeige in den Zellen AWT, Swing, JavaFX & SWT 8
D Swing Anzeige während eines Ladevorganges AWT, Swing, JavaFX & SWT 6
N Eigener Grafik Editor mit fehlerhafter Anzeige AWT, Swing, JavaFX & SWT 4
C SWT SWT Browser anzeige bug AWT, Swing, JavaFX & SWT 3
A Einschreiten vor anzeige eines Frames AWT, Swing, JavaFX & SWT 26
P JTree - Explorer mit nur eingeschränkter Anzeige AWT, Swing, JavaFX & SWT 17
J Verzögerung bei Änderungen der Anzeige abwarten AWT, Swing, JavaFX & SWT 5
T SWT Keine Anzeige der Widgets nach Comboauswahl AWT, Swing, JavaFX & SWT 2
M.F.G. Fehler bei der Anzeige Grafischer Elemente AWT, Swing, JavaFX & SWT 13
B SWT Textdatei Lesen und Anzeige in View - Zeichensatzproblem AWT, Swing, JavaFX & SWT 4
hdi JTree: interne Daten OK, Anzeige schwarze Magie AWT, Swing, JavaFX & SWT 2
R Anzeige der Aktivität AWT, Swing, JavaFX & SWT 3
S Splash Screen / "Loading" Anzeige im Programm AWT, Swing, JavaFX & SWT 27
S JTree - Anzeige des Knotennamen ändern AWT, Swing, JavaFX & SWT 2
B JList Anzeige aktualisieren (Models) AWT, Swing, JavaFX & SWT 2
G Keine Anzeige des Balkens AWT, Swing, JavaFX & SWT 3
C JTable aktualisiert die Anzeige nicht AWT, Swing, JavaFX & SWT 2
G Anzeige schwierigkeiten AWT, Swing, JavaFX & SWT 3
G Problem mit Anzeige von HTML AWT, Swing, JavaFX & SWT 5
P JRE 6 -> ToolTip & mnemonic Anzeige AWT, Swing, JavaFX & SWT 4
G JComboBox - Anzeige mit Wert verknüpfen AWT, Swing, JavaFX & SWT 3
G Anzeige Problem AWT, Swing, JavaFX & SWT 4
D Anzeige eines Bildes: JPanel oder JLabel ? AWT, Swing, JavaFX & SWT 3
T dynamische anzeige? AWT, Swing, JavaFX & SWT 4
W JList Anzeige erneuern AWT, Swing, JavaFX & SWT 4
P JMenuBar und JToolBar Anzeige Probleme AWT, Swing, JavaFX & SWT 5
T JComboBox anzeige AWT, Swing, JavaFX & SWT 6
F Anzeige von JPanel AWT, Swing, JavaFX & SWT 3
M JTree und Anzeige des entsprechenden Panels AWT, Swing, JavaFX & SWT 5
K Probleme mit der Anzeige eines einzigen Nodes in einem JTree AWT, Swing, JavaFX & SWT 9
S SWT-Widgets für Anzeige-Elemente AWT, Swing, JavaFX & SWT 3
G Keine Anzeige von Grafik bei externem paintComponent-Aufruf AWT, Swing, JavaFX & SWT 2
M GUI mit Swing erst nach Maximieren richtige Anzeige AWT, Swing, JavaFX & SWT 2
S Anzeige der Benutzeroberfläche verzögern AWT, Swing, JavaFX & SWT 10
G Anzeige von JTextField erneuern AWT, Swing, JavaFX & SWT 12
P DefaultTreeCellEditor -> Anzeige Probleme AWT, Swing, JavaFX & SWT 3
swek Flackernde Anzeige AWT, Swing, JavaFX & SWT 4
C Schweres Problem mit JDialog und Threads! Anzeige blockiert! AWT, Swing, JavaFX & SWT 5
A JTree-Anzeige filtern AWT, Swing, JavaFX & SWT 7
R Anfängerfrage:anzeige von Gui elementen AWT, Swing, JavaFX & SWT 2
W Anzeige von anderen Bildformaten: BMP, TIFF, PCX AWT, Swing, JavaFX & SWT 5
S Anzeige einer Progressbar. AWT, Swing, JavaFX & SWT 3
G Komponente zur Anzeige einer Textdatei. AWT, Swing, JavaFX & SWT 10
G JList: Anzeige von null-Werten verhindern AWT, Swing, JavaFX & SWT 3
I Problem mit korrekter Anzeige AWT, Swing, JavaFX & SWT 2
G Gibts ne Klasse zur Anzeige von Ziffern? AWT, Swing, JavaFX & SWT 4
S Anzeige-Wirrwar in JScrollbar AWT, Swing, JavaFX & SWT 3
B Anzeige eines SpinnerNumberModel AWT, Swing, JavaFX & SWT 3
D Layout einer scene mit ListView Elementen und Zwei Textfeldern AWT, Swing, JavaFX & SWT 1
J Event Handling Button "enablen" wenn Eingaben in Textfeldern korrekt sind AWT, Swing, JavaFX & SWT 1
P Text aus TextFeldern tauschen AWT, Swing, JavaFX & SWT 2
F Text von Textfeldern verarbeiten AWT, Swing, JavaFX & SWT 12
T Input-Check bei Textfeldern in Table AWT, Swing, JavaFX & SWT 5
P Formular mit n-Textfeldern generieren AWT, Swing, JavaFX & SWT 7
P Applet darstellung von Textfeldern Problem AWT, Swing, JavaFX & SWT 3
Z Wie kann ich Text unter den Textfeldern einfügen? AWT, Swing, JavaFX & SWT 3
E transparenz (alpha) - komisches aussehen von textfeldern! AWT, Swing, JavaFX & SWT 2
D Arbeiten mit 2 TextFeldern gleichzeitig AWT, Swing, JavaFX & SWT 6

Ähnliche Java Themen

Neue Themen


Oben