setVisible hält Programmausführung an, bis Dialog geschlossen wird. Wie nachmachen?

Ist nicht böse gemeint, aber weißt Du überhaupt, was genau der EDT ist, und wann man sich "im" EDT befindet?

Dein modalize() rufst Du in der main Methode auf, und das ist NICHT der EDT. Wenn Du modalize() aber z.B. in einen action listener reinlegst, dann bist du im EDT, und sofort funktioniert es nicht.

Ich meine, das ist doch auch die typische Anwendung. Man drückt irgendwo man auf einen Button, und dann will ich ein modales Fenster haben, aber das wird so nicht funktionieren.
 
was der EDT ist weiss ich. Wann sich in ihm befindet, darüber hatte ich mir bisher noch nicht so die Gedanken gemacht. ^^ Aber jetzt habe ich wieder was dazu gelernt.

Als ich ein modales JFrame gebraucht habe, hat das so getaugt, wie ich es oben geschrieben habe.

Jetzt haste mich aber auch neugierig gemacht, wie das das JOptionPane das macht. Guck dir mal die Sourcen dazu an. Wenn du die Methode showMessageDialog(...) aufrufst, wird irgendwann die veraltete Methode show aufgerufen und dann wirds interessant.

Die checken da ob man im EDT ist oder nicht. Wenn nicht, siehe meine Lösung von oben. Wenn man im EDT ist, dann wirds etwas komplexer.

/*
* @(#)Dialog.java 1.127 07/06/19
*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package java.awt;

Code:
public void show() {
        beforeFirstShow = false;
        if (!isModal()) {
            conditionalShow(null, null);
        } else {
            // Set this variable before calling conditionalShow(). That
            // way, if the Dialog is hidden right after being shown, we
            // won't mistakenly block this thread.
            keepBlocking = true;

            // Store the app context on which this dialog is being shown.
            // Event dispatch thread of this app context will be sleeping until
            // we wake it by any event from hideAndDisposeHandler().
            showAppContext = AppContext.getAppContext();

            AtomicLong time = new AtomicLong();
            Component predictedFocusOwner = null;
            try {
                predictedFocusOwner = getMostRecentFocusOwner();
                if (conditionalShow(predictedFocusOwner, time)) {
                    // We have two mechanisms for blocking: 1. If we're on the
                    // EventDispatchThread, start a new event pump. 2. If we're
                    // on any other thread, call wait() on the treelock.

                    modalFilter = ModalEventFilter.createFilterForDialog(this);

                    final Runnable pumpEventsForFilter = new Runnable() {
                        public void run() {
                            EventDispatchThread dispatchThread =
                                (EventDispatchThread)Thread.currentThread();
                            dispatchThread.pumpEventsForFilter(new Conditional() {
                                public boolean evaluate() {
                                    return keepBlocking && windowClosingException == null;
                                }
                            }, modalFilter);
                        }
                    };

                    // if this dialog is toolkit-modal, the filter should be added
                    // to all EDTs (for all AppContexts)
                    if (modalityType == ModalityType.TOOLKIT_MODAL) {
                        Iterator it = AppContext.getAppContexts().iterator();
                        while (it.hasNext()) {
                            AppContext appContext = (AppContext)it.next();
                            if (appContext == showAppContext) {
                                continue;
                            }
                            EventQueue eventQueue = (EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY);
                            // it may occur that EDT for appContext hasn't been started yet, so
                            // we post an empty invocation event to trigger EDT initialization
                            Runnable createEDT = new Runnable() {
                                public void run() {};
                            };
                            eventQueue.postEvent(new InvocationEvent(this, createEDT));
                            EventDispatchThread edt = eventQueue.getDispatchThread();
                            edt.addEventFilter(modalFilter);
                        }
                    }

                    modalityPushed();
                    try {
                        if (EventQueue.isDispatchThread()) {
                            /*
                             * dispose SequencedEvent we are dispatching on current
                             * AppContext, to prevent us from hang.
                             *
                             */
                            // BugId 4531693 (son@sparc.spb.su)
                            SequencedEvent currentSequencedEvent = KeyboardFocusManager.
                                getCurrentKeyboardFocusManager().getCurrentSequencedEvent();
                            if (currentSequencedEvent != null) {
                                currentSequencedEvent.dispose();
                            }

                            /*
                             * Event processing is done inside doPrivileged block so that
                             * it wouldn't matter even if user code is on the stack 
                             * Fix for BugId 6300270
                             */

                             AccessController.doPrivileged(new PrivilegedAction() {
                                     public Object run() {
                                        pumpEventsForFilter.run();
                                        return null;
                                     }
                             });
                        } else {
                            synchronized (getTreeLock()) {
                                Toolkit.getEventQueue().postEvent(new PeerEvent(this,
                                                                                pumpEventsForFilter,
                                                                                PeerEvent.PRIORITY_EVENT));
                                while (keepBlocking && windowClosingException == null) {
                                    try {
                                        getTreeLock().wait();
                                    } catch (InterruptedException e) {
                                        break;
                                    }
                                }
                            }
                        }
                    } finally {
                        modalityPopped();
                    }

                    // if this dialog is toolkit-modal, its filter must be removed
                    // from all EDTs (for all AppContexts)
                    if (modalityType == ModalityType.TOOLKIT_MODAL) {
                        Iterator it = AppContext.getAppContexts().iterator();
                        while (it.hasNext()) {
                            AppContext appContext = (AppContext)it.next();
                            if (appContext == showAppContext) {
                                continue;
                            }
                            EventQueue eventQueue = (EventQueue)appContext.get(AppContext.EVENT_QUEUE_KEY);
                            EventDispatchThread edt = eventQueue.getDispatchThread();
                            edt.removeEventFilter(modalFilter);
                        }
                    }

                    if (windowClosingException != null) {
                        windowClosingException.fillInStackTrace();
                        throw windowClosingException;
                    }
                }
            } finally {
                if (predictedFocusOwner != null) {
                    // Restore normal key event dispatching
                    KeyboardFocusManager.getCurrentKeyboardFocusManager().
                        dequeueKeyEvents(time.get(), predictedFocusOwner);
                }
            }
        }
    }
 
Jetzt haste mich aber auch neugierig gemacht, wie das das JOptionPane das macht. Guck dir mal die Sourcen dazu an. Wenn du die Methode showMessageDialog(...) aufrufst, wird irgendwann die veraltete Methode show aufgerufen und dann wirds interessant.

Ja, mich interessiert das auch sehr, und zwar schon seit Monaten :) Nicht nur JOptionPane macht das so, auch JDialog.

Vielleicht sage ich mal ein wenig was zum Hintergrund, warum ich das ganze überhaupt brauche. Ich möchte eine eigene Dialog-Klasse (abgeleitet von JDialog) haben, die eine Öffnen-Animation abspielt, ähnlich wie bei Windows, wenn das Fenster größer wird, wenn man es maximiert. Um dies zu erreichen, muss ich diese Animation als SwingWorker abspielen, aber der aktuelle Programmfluss muss dann gestoppt werden. Wenn die Animation fertig ist, soll das Programm weiter laufen und der JDialog wird geöffnet.

Das hat natürlich nicht direkt was mit einem modalen Fenster zu tun, aber es ist genau das, was setVisible macht - nämlich den Programmfluss zu stoppen und das direkt im EDT, ohne dass die GUI steht. Ich habe das in meinem aktuellen Programm zwar gelöst, aber unheimlich umständlich, durch Reflection, indem wir angebe, weile Methode nach der Animation aufgerufen werden soll. Das ist sehr unschön und fehleranfällig und ich würde sonstwas dafür geben, wenn ich das durch guten Code ersetzen kann :)

Und der setVisible Code ist da der Schlüssel dazu.

Die checken da ob man im EDT ist oder nicht. Wenn nicht, siehe meine Lösung von oben. Wenn man im EDT ist, dann wirds etwas komplexer.

Ja, ich hatte mir den Code auch schonmal angeguckt, aber ich muss zugebeb, dass er sich mir nicht erschließen will. Aber vielleicht können wir uns ja gemeinsam ein wenig da rantasten. Ich werde ihn mir heute Abend nochmal ganz genau ansehen, vielleicht gewinnen wir ja wirklich ein paar Erkenntnisse darüber, würde mich freuen :)
 
Hallo Florian,

konntest Du inzwischen schon irgendwelche Erkenntnisse aus dem Code von Sun gewinnen? Ich weiß wirklich nicht wie die das machen, es funktionioert augenscheinlich, aber ich kappier den Code einfach nich :-/
 
Hallo!
Ich wollte heute nochmal fragen ob es dabei mittlerweile einen Fortschritt gibt.
Habe genau das gleiche Problem.
Bin auch dabei die show() Methode vom JDialog zu zerpflücken.
Ist aber nicht ganz so trivial...

Interessant z.B:

Java:
final Runnable pumpEventsForFilter = new Runnable() {
                        public void run() {
                            EventDispatchThread dispatchThread =
                                (EventDispatchThread)Thread.currentThread();
                            dispatchThread.pumpEventsForFilter(new Conditional() {
                                public boolean evaluate() {
                                    return keepBlocking && windowClosingException == null;
                                }
                            }, modalFilter);
                        }
                    };
 
Hallo benhaze,

sorry dass ich mich so spät melde, ich habe die Benachrichtigung, dass sich hier was getan hat, ganz übersehen.

Leider konnte ich noch keine Fortschritte machen. Ich habe mich aber in den letzten Wochen auch nicht mit dieser Problematik beschäftigen können. Dennoch bin ich immer sehr interessiert daran, eine solche Lösung zu finden. Dass es geht, da bin ich mir sicher - denn Sun's code macht ja nichts anderes.

Wahrscheinlich muss man erstmal eine sehr gute Kenntnisse der Swing-Event und Paint-Interna haben, bevor man da durchsteigt.
 

Neue Beiträge

Zurück