Wer oder was bestimmt welches Frame toFront kommt wenn ein anderes geschlossen wird?

Thallius

Top Contributor
Hi,

ich habe hier ein sehr merkwürdiges Verhalten meiner Anwendung.

Ich habe ein "MainFrame" (JFrame) das ich bei Anwendungsstart öffne. Wähle ich nun in diesem Frame einen Menupunkt aus, so erstelle ich einen Controller nennen wir ihn "ActionController" und der öffnet ein neues JFrame "ActionFrame". Dieser Controller muss zunächst Daten laden. Deshalb öffne dfer Controller wiederum ein weiteres JFrame nennen wir es "CancelFrame" welches einen Langzeitbalken und einen CancelButton enthält. Dieses Cancelframe bekommt noch das alwaysOnTop Attribut. Nach dem Öffnen des CancelFrames starte ich einen Swingworker, welcher die Daten läd. Ist der Worker fertig, so ruft die done() Methode des Workers ein Methode dataloaded() in meinem ActionController auf. Dieser schließt nun das CancelFrame mit

Code:
if(cancelDialog != null)
    cancelDialog.close();
cancelDialog = null;

Das close im cancelDialog macht einfach nur ein

Code:
if(frame != null)
    frame.setVisible(false);

In dem Moment schließt sich das CancelFrame und das MainFrame kommt in den Vordergrund und überdeckt das ActionFrame, welches vorher noch vor dem MainFrame war.

Selbst wenn ich nach dem canclDialog.close() noch ein actionFrame.toFront() mache, kommt trotzdem das MainFrame nach vorne.

Woran kann das liegen. Wie kann ich das debuggen?

Jede Anregung ist herzlich willkommen.

Gruß

Claus
 
Gerade noch was ausprobiert.

Mache ich nach dem cancelDialog.close() ein

Code:
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                actionFrame.toFront();
            }
        });

dann kommt erst das MainPanel nach vorne und kurz danach das ActionPanel wieder vor. Also schein es ja so, als würde im EDT noch ein MainFrame.toFront() in der Queue hängen. Aber wo kommt das her?
 
--DISCMLAIMER: pure Spekulation! --

Ich vermute mal, da sowohl das CancelFrame als auch das ActionFrame beide "aus dem MainFrame heraus" geöffnet werden versucht Spring nach dem Schließen eines der beiden wieder zum vorherigen Frame, also dem MainFrame, zurückzukehren. Ich denke Swing kann das zuordnen, weil das öffnen der neuen Frames innerhalb des UI-Events passiert. Du kannst versuchen das invokeLater direkt da zu benutzen, wo die beiden neuen Frames geöffnet werden.
 
Erstmal danke für die Antwort aber so ist es ja gerade nicht.

Also das MainFrame hat natürlich einen eigenen Controller mainController. Dieser öffnet das MainFrame. Wird jetzt im MainFrame der Menupunkt aktiviert, schickt dieser per Listener an seinen Controller das Commando. Der mainController erstellt dann einen actionController und dieser öffnet erst das ActionFrame und dann das CancelFrame und startet dann den SwingWorker.

Gruß

Claus
 
Du hast recht.

ich habe jetzt das Öffnen des CancelFrames und das Starten des Swingworkers in ein invokdeLater gesetzt und es funktioniert. Nicht schön aber was will man machen. Anscheinend ist Swing tatsächlich nicht in der Lage festzustellen, dass zwischen dem MainFrame und CancelFrame noch das ActionFrame geöffnet wurde.

btw gibt es eigentlich eine schönere Lösung im runable block this zu benutzen?

Code:
        cancelLister = this; // hier der Fusch, damit ich auf this zugreifen kann
        SwingUtilities.invokeLater(new Runnable() 
        {
            public void run() 
            {
                cancelDialog=new CancelDialog("Download", "Downloading Fieldengineer Tools","LOAD_SYSTEMTOOLS", listFrame.getFrame()); 
                cancelDialog.setCancelActionListener(cancelLister);
                cancelDialog.progressBar.setIndeterminate(true);
                cancelDialog.progressBar.setMaximum(0);
                cancelDialog.frame.setLocationRelativeTo(listFrame.getFrame());

                worker = new DownloadWorker();
                worker.execute();
            }
        });

Gruß

Claus
 
Nicht, dass ich wüste. Ein Lambda erlaubt dir das; aber ich vermute du kannst Lambdas nicht benutzen, sonst wärst du selbst schon drauf gekommen:

Java:
SwingUtilities.invokeLater(() -> {
    // ...
    cancelDialog.setCancelActionListener(this);
    // ...
});
 

Zurück
Oben