JavaFX: TextArea updated nicht

Kababär

Top Contributor
Hi,

normalerweise weiß ich, wie man die GUI aus einem anderen oder dem selben Thread updated, doch leider funktioniert es diesmal nicht und ich weiß nicht woran es liegt.
Das Problem ist, dass die GUI bzw. die TextArea nicht geupdated wird.
Vielleicht kann mir jemand helfen?

Ich habe mir eine kleine Hilfsmethode gebastelt, um festzustellen, ob ich mich derzeit im FX Thread befinde oder nicht und führe dementsprechend mein Runnable aus:
Code:
    private void runSafe(Runnable runnable) {
        Objects.requireNonNull(runnable, "runnable");
        if (Platform.isFxApplicationThread()) {
            System.out.println("On FX Thread");
            runnable.run();
        } else {
            System.out.println("Not on FX Thread");
            Platform.runLater(runnable);
        }
    }

Die Methode befindet sich in meiner Controller-Klasse und indirekt durch die Main aufgerufen:
Code:
 @Override
    public void start(Stage stage) throws Exception {
        FXMLController cnt = new FXMLController("Mit Header", "und mit Content");
        cnt.setAppendType(AppendType.END);

        Scene scene = new Scene(cnt);
        scene.getStylesheets().add("/styles/Styles.css");
        stage.setTitle("JavaFX and Maven");
        stage.setScene(scene);
        stage.show();

        cnt.appendLog(42);
        for (int i = 0; i < 200000000; i++) {
            int k = 55;
            int l = 55 + 22 << 2;
            int f = l + k - 200;
            int x = k * l - f ^ 2;
            int y = x + i;
            cnt.append(y, true);
        }

        cnt.append(0110, true);

    }

Der FXMLController ruft seine View selbst auf. Es geht um die letzten Zeilen ab "cnt.appendLog(42)".
In appendLog(...) passert nicht mehr als das der Text der TextArea mit dem Parameter von appendLog(...) konkateniert wird und dann wird
Code:
  runSafe(() -> {
            logArea.appendText(s);
        });

aufgerufen.


Wo ist das Problem?

Wenn ich das Programm starte, dann wird zwar eine Stage anzeigt, die aber nur grau ist und alle Komponenten fehlen. Erst wenn du Schleife zuende ist, werden die Komponenten angezeigt. Aber ich will ja, dass die Stage geladen wird und im Hintergrund soll man die GUI updaten können.
 
Zuletzt bearbeitet:
Dass heißt, dass die Elemente erst nach der for Schleife dem Stage hinzugefügt werden. Dadurch wird dieser Effekt sichtbar.
 
Zuletzt bearbeitet:
Habe gerade eine neue Erkenntnis "bekommen":
Die GUI verliert komplett den Fokus.
Habe mir mal einen Tester geschrieben, der die Methode foo() ausführt, sobald ein Button gedrückt wird.
Die Methode wird aufgerufen und nach der Methde ist die GUI immer noch "tot" (Keine Rückmeldung).

Code:
public class GUITester {

    private FXMLController cnt;

    public GUITester(FXMLController cnt) {
        this.cnt = cnt;
    }

    public void foo() {
        cnt.appendLog(42);
        for (int i = 0; i < 20; i++) {
            int k = 55;
            int l = 55 + 22 << 2;
            int f = l + k - 200;
            int x = k * l - f ^ 2;
            int y = x + i;
            cnt.append(y, true);
        }

        cnt.append(0110, true);
    }

}
 
Mir ist keine Möglichkeit bekannt, wie man das in JavaFX machen könnte 😀
Eigentlich sollte die Stage automatisch refreshen.

Fehler gefunden: in der Hilfsmethode habe ich einfach nur run(); auf das Interface Runnable angwendet, es muss aber einem Thread übergeben werden, der dann start() aufruft.
 
Zuletzt bearbeitet:
Bist du sicher, dass die Schleife nicht auf dem UI-Thread läuft? Denn die Beschreibung der leeren Stage, die sich erst updated, nachdem alles durch ist, klingt so, als würde die Schleife nicht auf einem anderen Thread laufen. In dem Fall hilft dir dein Helper nicht (den ich so in etwa auch verwende). Du blockierst ansonsten nämlich einfach nur den UI-Thread...
 
Meine Helper-Methode gibt immer "On FX Thread" aus. Den GuiTester initialisiere ich in der Main (wo die Main Methode ist und start überschrieben wird). Und dort rufe ich auch die Methode foo auf.
Wenn ich in der Helper-Methode
Code:
runnable.run ()
mit
Code:
new Thread (runnable).start ();
ersetze, funktioniert es. Das löst die Problematik mit dem Blocken.

Allerdings nicht zuverlässig wie ich feststellen musste. In einem anderen Projekt hab ich das gleiche versucht, aber die GUI freezt solange der Auftrag nicht fertig ist (die Schleife von 1 bis 100000, appende jedes i an die selbe Textarea). Die Einträge sind auch nicht in der richtigen Reihenfolge. Mit join () kann ich letzteres Problem beheben, aber ersteres bleibt bestehen.

Ich werde später mal den Code posten. Vielleicht kann mir ja jemand mit dem Verständnis weiterhelfen.

Meine Vermutung allerdings ist, dass die GUI zu schnell geupdatet wird und mit dem zeichnen nicht hinterherkommt. (Habe es deswegen auch mit einer BlockingQueue der Größe 1 in kombination mit einem AnimationTimer versucht, allerdings erfolgslos). Die Stage bleibt komplett ausgegraut und nicht mal die injected components werden angezeigt, weder von der sekundären noch von der Main Stage.

Code zeige ich später, bin gerade unterwegs.
 

Neue Themen


Zurück
Oben