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

DarthShader

Erfahrenes Mitglied
Hallo,

die setVisible Methode eines JDialogs hält den aktuellen Thread an und führt das Programm weiter, nachdem der Dialog geschlossen wurde (dabei ist das besondere, dass trotzdem noch Events verarbeitet werden, weil anscheinend eine Art neuer Event-Dispatch-Thread aufgemacht wird).

Wie kann ich dies nachbilden, mit einer Methode meiner eigenen Klasse? Ich hab wirklich überhaupt keine Idee, wie die das mit der setVisible aus JDialog machen?!


Für ein paar Tipps wäre ich sehr dankbar!


Danke für Eure Hilfe
 
Du kannst deinen Thread über .wait() anhalten und dann in deinem Fenster beim Schließen-Event den Process wieder aufwecken.

Ich hoffe das reicht dir als Tipp.
 
Hallo Florian,

danke für Deine Antwort, aber

Du kannst deinen Thread über .wait() anhalten und dann in deinem Fenster beim Schließen-Event den Process wieder aufwecken.

Ich hoffe das reicht dir als Tipp.

so trivial ist das Problem leider nicht. Wenn ich den EDT per wait anhalte, dann funktioniert die GUI nicht mehr, es werden also auch im Dialogfenster keine Events mehr verarbeitet. Deswegen sagte ich ja, dass man irgendwie einen neuen EDT aufmachen müsste, damit die Oberfläche überhaupt noch reagiert (denn beachte, son JDialog.setVisible ruft man ja aus dem EDT heraus auf, und genau sowas will ich nachbilden mit einer eigenen Methode).
 
guck mal hier, wenn du die Methode in dein JFrame einbaust, kannst du durch modalize dein Programm anhalten, bis das Fenster geschlossen wird.
Code:
   public void modalize()
   {
      final Object MODALLOCK = new Object();
      
     addWindowListener (new WindowAdapter(){
         public void windowClosed (WindowEvent e)
         {
            synchronized (MODALLOCK){
               MODALLOCK.notifyAll();
            }
         }
      });

      synchronized (MODALLOCK){
         try {
             MODALLOCK.wait();
          }catch (InterruptedException ex) {
             Thread.currentThread().interrupt();
          }
      }
   }
 
Hallo Florian,

danke für das Codebeispiel. Wie soll das denn später verwendet werden, etwa so

Java:
myFrame.modalize();
myFrame.setVisible(true);

? Aber mit "MODALLOCK.wait();" wird ja der Thread angehalten, das heißt, "myFrame.setVisible(true);" wird nicht mehr erreicht.

Und ganz allgemein: wenn die modalize() Methode aufgerufen wird, und es handelt sich um den Event-Dispatch-Thread (EDT), dann werden doch keine Events mehr verarbeitet, oder? Bleibt die GUI dann nicht einfach stehen?

Ich habe Dein Beispiel noch nicht praktisch ausprobiert, ich würde mich sehr freuen, wenn Du mir bei den obigen Fragen nochmal auf die Sprünge helfen könntest.

Danke!
 
genau anders herum
Code:
myFrame.setVisible(true);
myFrame.modalize();

Hab das schonmal verwendet, ohne Probleme. Dein Gui hängt nicht.

Du könntest auch die setVisible Methode überschreiben. Habs aber nicht getestet, ob das läuft, Hier mal aus dem Bauch heraus.
Code:
public setVisible(boolean visible){
  super.setVisible(visible);
  if(visible){
     modalize();
 }else{
   //hier musst du testen ob bei setVisible(false) auch das closing event ausgelöst wird, ich 
  //denke schon, falls nicht, musst du hier im else den lock selbst aufheben.
}
}
 
Hab das schonmal verwendet, ohne Probleme. Dein Gui hängt nicht.

Du könntest auch die setVisible Methode überschreiben. Habs aber nicht getestet, ob das läuft, Hier mal aus dem Bauch heraus.

Es hängt nicht? Also das verstehe ich nicht. Ich meine, es ist grandios, dass das funktioniert, ich hätte sonst absolut nicht gewusst, wie ich so eine wartende Funktion im EDT machen kann.

Du rufst das aber auch aus dem EDT heraus auf, oder? Sprich, die Methode "EventQueue.isDispatchThread()" gibt true zurück?

Aber wieso stopp die Geschichte dann nicht. Wenn ich im EDT z.B. ne Schleife baue, die lange braucht um abzuarbeiten, dann steht die GUI ja auch, was ja auch logisch ist. Aber per .wait nicht? Achtet das Laufzeitsystem vielleicht explizit darauf, und macht in dem Fall tatsächlich einen neuen EDT im Hintergrund auf? Ich kann dazu aber in keiner Dokumentation etwas finden.

Also das Thema ist für mich gerade wirklich mysteriös :)


Edit:

Also ich habe es jetzt auch mal selbst ausprobiert, und es ist genau das Phänomen, was ich voraus gesagt habe. Leider reagiert die GUI dann nicht mehr. Also entweder, Du hast Dich irgendwie total vertan, oder ich mache etwas total falsch :) Hier ist mein Test-Code, vielleicht hast Du ja Lust, den auch mal eben auszuprobieren:

Java:
public class ModalTest
{
	@SuppressWarnings( "serial" )
	class MyFrame extends JFrame
	{
		public void modalize()
		{
			final Object MODALLOCK = new Object();

			addWindowListener( new WindowAdapter()
			{
				public void windowClosed( WindowEvent e )
				{
					synchronized ( MODALLOCK )
					{
						MODALLOCK.notifyAll();
					}
				}
			} );

			synchronized ( MODALLOCK )
			{
				try
				{
					MODALLOCK.wait();
				}
				catch ( InterruptedException ex ) { Thread.currentThread().interrupt(); }
			}
		}
	}
	
	public ModalTest()
	{
		JButton button = new JButton( "Fenster öffnen" );
		button.setSize( 200, 80 );
		button.addActionListener( new ActionListener()
		{
			@Override
			public void actionPerformed( ActionEvent arg0 )
			{
				System.out.println( EventQueue.isDispatchThread() );
				
				MyFrame frame = new MyFrame();
				frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
				frame.setSize( 400, 300 );
				
				frame.setVisible( true );
				frame.modalize();
			}
		});

		JFrame frame = new MyFrame();
		frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
		frame.setSize( 800, 600 );
		frame.setLocationRelativeTo( null );
		frame.setLayout( null );
		frame.add( button );
		frame.setVisible( true );
	}

	public static void main( String[] args )
	{
		new ModalTest();
	}

}

Das Programm öffnet ein Fenster mit einem Button. Beim Klick auf den Button soll sich das neue, modale Fenster öffnen (ich rufe ja auch modalize() auf). Aber siehe, der Inhalt des neuen Fensters wird nicht mehr gezeichnet, und es kann nicht geschlossen werden, weil der Event-Dispatch-Thread (EDT) geblockt wird.

Siehst Du, was ich meine? Mach ich etwas falsch?
 
Zuletzt bearbeitet:
komisch... es ist zwar schon ne weile her, aber bei mir hat das geklappt... bin mir eigentlich sicher, dass es mit der modalize Funktion geklappt hat.

Falls ich heute noch mal dazu komme teste ich es mal.
 
Habs mal schnell selber programmiert. Bei mir läuft es. Ich kann den Knopf drücken so viel ich will. Und wenn ich das Fenster schließe, dann kommt erst die fertig Meldung nach dem Aufruf der modalize Methode. Hier mein Code. Ich guck mal gleich noch dein Beispiel an.

Code:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JPanel;
import javax.swing.JFrame;
import javax.swing.JButton;

public class ModalTest extends JFrame {

	private static final long serialVersionUID = 1L;

	private JPanel jContentPane = null;

	private JButton jButton = null;

	/**
	 * This is the default constructor
	 */
	public ModalTest() {
		super();
		initialize();
	}

	/**
	 * This method initializes this
	 * 
	 * @return void
	 */
	private void initialize() {
		this.setSize(300, 200);
		this.setContentPane(getJContentPane());
		this.setTitle("JFrame");
		this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
	}

	/**
	 * This method initializes jContentPane
	 * 
	 * @return javax.swing.JPanel
	 */
	private JPanel getJContentPane() {
		if (jContentPane == null) {
			jContentPane = new JPanel();
			jContentPane.setLayout(new BorderLayout());
			jContentPane.add(getJButton(), BorderLayout.CENTER);
		}
		return jContentPane;
	}

	/**
	 * This method initializes jButton
	 * 
	 * @return javax.swing.JButton
	 */
	private JButton getJButton() {
		if (jButton == null) {
			jButton = new JButton();
			jButton.setText("KLICK MICH!");
			jButton.addActionListener(new ActionListener() {

				public void actionPerformed(ActionEvent e) {
					System.out.println("Gui reagiert noch...");
				}

			});
		}
		return jButton;
	}

	public void modalize() {
		final Object MODALLOCK = new Object();
		addWindowListener(new WindowAdapter() {
			public void windowClosed(WindowEvent e) {
				synchronized (MODALLOCK) {
					MODALLOCK.notifyAll();
				}
			}
		});
		synchronized (MODALLOCK) {
			try {
				MODALLOCK.wait();
			} catch (InterruptedException ex) {
				Thread.currentThread().interrupt();
			}
		}
	}

	public static void main(String[] args) {
		ModalTest m = new ModalTest();
		m.setVisible(true);
		m.modalize();
		System.out.println("fertig");
		System.exit(0);
	}

}
 
Komisch, bei dir liefert

System.out.println(EventQueue.isDispatchThread());

immer true zurück. Bei mir immer false...

Der einzige Unterschied ist, dass du das Fenster aus einem Fenster erzeugst... Jetzt bin ich auch Planlos.
 

Neue Beiträge

Zurück