2013-07-31 14 views
5

Um ein wenig mehr zu erklären, habe ich eine GUI, die wie folgt aussieht:GUI nicht visuell Aktualisierung vor Action läuft

enter image description here

Dann habe ich eine Aktion Hörer auf die OK-Taste, die wie beginnt:

//OK Button Action Listener 
private void okButtonActionPerformed(ActionEvent e) { 
    //Enable/Disable Buttons 
    okButton.setEnabled(false); 
    cancelButton.setEnabled(true); 
    updateCheckbox.setEnabled(false); 
    //Move on to a series of other methods here... 

die in der Theorie sollte, damit dies geschieht:

enter image description here

Doch statt, erhalte ich die folgende, bis alle Methoden und andere mit der OK-Taste verbunden Dinge abgeschlossen sind:

enter image description here

Das ist offensichtlich nicht geschehen kann, weil die Idee der Löschtaste zu machen ist verfügbar und der OK-Button und einige andere Tick-Boxen für die Dauer des Programms nicht verfügbar (Bild 2), wo es stattdessen in einem Halbzustand einfriert (Bild 3). Gibt es eine Möglichkeit, das zu bekämpfen?

+0

alles in actionListener ist in einem Moment getan (auf dem Bildschirm), nachdem alle Codezeilen ausgeführt werden, bitte was wirklich Ziel ist – mKorbel

+0

Ich habe eine harte Zeit zu verstehen, was genau Sie meinen, aber im Wesentlichen habe ich eine lange laufender Prozess, der ausgeführt werden muss, während gleichzeitig die GUI verfügbar bleibt. Basierend auf anderen Antworten sollte ich einen anderen Thread über 'SwingWorker' verwenden. – JTApps

+0

Ich habe einen langwierigen Prozess ---> dann folgt und akzeptiere hier eine der Antworten, Codexemplare, einige davon mit excellenten Beschreibungen – mKorbel

Antwort

6

Jedesmal, wenn Sie Logik von der GUI führen Sie die Swingworker in der folgenden Art und Weise verwenden sollten:

SwingWorker myWorker= new SwingWorker<String, Void>() { 
    @Override 
    protected String doInBackground() throws Exception { 
     //Execute your logic 
     return null; 
    } 
}; 
myWorker.execute(); 

Wenn Sie die GUI aus dem Inneren dieser Logik Verwendung invokeLater aktualisieren möchten:

SwingUtilities.invokeLater(new Runnable() { 
    @Override 
    public void run() { 
     //To update your GUI 
    } 
}); 

Damit können Sie sicher sein, dass sowohl Ihre Logik als auch Ihre GUI reaktionsfähig bleiben.

Edit:

Sie auch invokeAndWait nutzen könnten, wenn dies Ihre Bedürfnisse mehr passt. Link to related answer

+0

Äh, nicht so sehr. Es gibt einen vollkommen guten Rahmen innerhalb des 'SwingWorker', um zwischenzeitliche Aktualisierungen mit' publish' und 'process' zurückzugeben; Warum in aller Welt würdest du 'invokeLater' benutzen ?! –

+0

Die Logik, der ich folge, ist hier: http://Stackoverflow.com/a/7196920/1611957 Könnten Sie erklären, warum es nicht gilt? Ich meine - es macht es einfach. – bjedrzejewski

+0

Da der 'SwingWorker' bereits eine asynchrone Aufgabenwarteschlange hat, können Sie Elemente in 'process' übergeben und dann ruft der EDT' publish' auf. Sie überschreiben 'publish' und verwenden das Element, um die GUI zu aktualisieren. Ihre Methode erfordert die Erstellung einer anderen anonymen Klasse (nämlich die 'Runnable') und wenn Sie irgendwelche Daten hineingeben wollen, dann muss es' final' etc. sein. Auch müssen Sie die Thread-Sicherheit berücksichtigen, da die 'Runnable' aufgerufen wird von der EDT. –

3

// hier auf eine Reihe von anderen Methoden Move on ...

sicher Machen Sie den GUI-Thread (EDT) mit langer Laufzeit Operationen nicht blockieren. Verwenden Sie stattdessen SwingWorker.

3

Machst du etwas Verarbeitung auf dem gleichen Thread, der die GUI behandelt? Vielleicht möchten Sie in einen SwingWorker Thread schauen, um die heavy stuff im Hintergrund zu tun, so dass Ihre Benutzeroberfläche reaktiv bleibt, wenn dies der Fall ist.

+0

Das ist genau das, was ich mache und ich sehe, was ich falsch mache. Ich muss jetzt einfach versuchen, einen anderen Thread zu implementieren. – JTApps

3

Yup, das ist, weil Sie mit EDT mit Ihren anderen Methoden blockiert haben.

Sie müssen eine andere Thread verwenden, um die Arbeit im Hintergrund zu tun, sonst wird die GUI blockiert.

In Swing-Anwendungen wird empfohlen, lange laufende Aufgaben an einem SwingWorker auszuführen.

Werfen Sie einen Blick auf die für eine Einführung.

Ein SwingWorker führt eine Aufgabe aus, die ihm gegeben wird, und kann es an die GUI melden, wenn es fertig ist. Dies geschieht nicht blockierend, so dass Sie die GUI während der Ausführung der Aufgabe weiterhin verwenden können.

Wenn Sie die Hintergrundaufgabe abbrechen möchten, müssen Sie einen Verweis auf die SwingWorker halten, damit Sie die cancel Methode aufrufen können. In diesem Fall muss die Arbeitsmethode unterbrechbar sein, andernfalls kann die Aufgabe nicht abgebrochen werden.

+0

Abbrechen wird in diesem Fall das Programm einfach vollständig beenden, anstatt es zu unterbrechen. Die Art und Weise, wie die verschiedenen Antworten es klingen lassen, scheint so zu sein, als würde es eine große Umstrukturierung des Codes erfordern, die ich NICHT machen möchte. Ich könnte es aber falsch interpretieren. Würden Sie vorschlagen, den gesamten Action-Listener-Code, der nicht mit der GUI verwandt ist, mit SwingWorker zu verpacken? – JTApps

+0

Ja, das sollten Sie tun. Wenn Sie während der Verarbeitung GUI-Aktualisierungen bereitstellen möchten, veröffentlichen Sie Aktualisierungen mithilfe der 'publish'-Methode und überschreiben die' process'-Methode. Die "process" -Methode wird auf dem EDT ausgeführt, wodurch Swing's single-threaded-Modell nicht zerstört wird. –

+0

Ich mache jetzt meine Forschung, aber ich habe ein kleines bisschen Probleme mit der Logik. Zum Beispiel, wenn ich 'cancelButton.setEnabled (true)' 'tun wollte, während ich die' doSomething() 'Methode ausführte, wie würde das aussehen? Eine visuelle Darstellung der Logik hier würde mir helfen, sie am besten anzuwenden. – JTApps