JDialog & invokeLater

feigline

Grünschnabel
€dit: Mist, ich merke gerade, dass der Thread besser in Swing / AWT / SWT gepasst hätte, sorry :\ Wäre vielleicht jemand so nett, den dorthin zu verschieben? Schonmal danke.


Hi,

ich weiß nicht, wie ich den Thread hier genau nennen soll, aber ich hoffe mal, es wird gleich ersichtlich, wo mein Problem liegt und zwar möchte ich via JOptionPane und createDialog ein Dialogfenster erstellen und anzeigen. Das ist nicht weiter schwierig.

Code:
import javax.swing.*;

public class Main
{
    public static void main(String[] args)
    {    
        JOptionPane pane = new JOptionPane(new Object[]{"test text"});
                  
        JDialog dialog = pane.createDialog(null, "test caption");
        dialog.setModal(false);
        dialog.pack();
        dialog.setVisible(true);
    }
}
Funktioniert auch alles einwandfrei.

Nun allerdings muss ich das in Verbindung bringen mit SwingUtilities.invokeLater. Das habe ich auf folgende Weise probiert:

Code:
import javax.swing.*;

public class Main
{
    public static void main(String[] args)
    {    
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
               {
                JOptionPane pane = new JOptionPane(new Object[]{"test text"});
                  
                JDialog dialog = pane.createDialog(null, "test caption");
                dialog.setModal(false);
                dialog.pack();
                dialog.setVisible(true);
                
                try
                {
                    Thread.sleep(3000);
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                }
                
                System.exit(0);
               }
        });        
    }
}
Das Problem hierbei ist, dass das Dialogfenster so aussieht:

http://feigling.php-4.info/darstellung.JPG

also das Fenster garnicht richtig aufgebaut wird. Und zwar liegt das an SwingUtilities.invokeLater. Das Problem ist jetzt aber, dass im eigentlichen Projekt dieses invokeLater benutzt werden muss (soweit ich weiß - den Teil hat jemand anders gemacht ;x)

Funktionieren tut es, wenn ich das Fenster modal mache, allerdings wird Code nach dialog.setVisible(true); natürlich erst ausgeführt, wenn ich auf den Button im Dialog geklickt habe. Im richtigen Projekt wird es da allerdings keinen Button geben. Naja, langer Text, kurze Frage: Weiß jemand, wie ich das Fenster korrekt anzeigen lasse mit SwingUtilities.invokeLater und ohne das Fenster modal zu setzen? ich habe da jetzt bestimmt 10 Stunden dran gesessen und probiert und es jetzt soweit einschränken können wie oben zu sehen ist. Ich weiß so langsam nicht mehr weiter. Was ich weiß ist, dass Swing nicht threadsave ist und dass man darum SwingUtilities.invokeLater benutzt, daher verstehe ich nicht, warum es zu so nem Anzeigenfehler kommt.

Das

Code:
try
                {
                    Thread.sleep(3000);
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                }
könnte man auch rauslassen, allerdings sieht man den Dialog dann natürlich nur ganz kurz. Also am Sleep liegt das nicht, dass der Dialog falsch dargestellt wird.

Ausserdem habe ich es mal so probiert:

Code:
import javax.swing.*;

public class Main
{
	public static void main(String[] args)
	{
		SwingUtilities.invokeLater(new Runnable()
		{
			public void run()
		   	{
				JDialog dialog = new JDialog();
				dialog.setSize(100, 100);
				dialog.setVisible(true);
				
				try
				{
					Thread.sleep(3000);
				}
				catch(Exception e)
				{
					e.printStackTrace();
				}
				
				System.exit(0);			
		   	}
		});	
	}
}

Was auch nicht so läuft wie es soll. Ich bin ganz ehrlich gesagt etwas ratlos. Hätte vielleicht jemand eine Idee, wodran das liegen könnte und wie ich es zum Laufen bekomme?
 
Zuletzt bearbeitet:
Hallo!

Das Problem ist, dass du mit Thread.sleep(...) den EDT (Event Dispatch Thread) schlafen legst, der dann die GUI nicht mehr neuzeichnen kann... wenn du in einem externen Thread wartest hast du keine Probleme... Wenn du nach dieser Wartezeit aus diesem Thread wieder Manipulation an der GUI durchfuehren willst musst du natuerlich wieder ueber den EDT gehen um auf der sicheren Seite zu sein. (EventQueue.invokeLater(..), EventQueue.invokeAndWait(...) bzw. SwingUtilities...

Schau mal hier:
Java:
/**
 * 
 */
package de.tutorials;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

/**
 * @author Tom
 * 
 */
public class DialogExample {
    public static void main(String[] args) {
        final Timer timer = new Timer(3000,new ActionListener(){
            public void actionPerformed(ActionEvent e) {
                    System.exit(0);
            }
        });
        
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JOptionPane pane = new JOptionPane(new Object[] { "test text" });

                JDialog dialog = pane.createDialog(null, "test caption");
                dialog.setModal(false);
                dialog.pack();
                dialog.setVisible(true);
                timer.start();
            }
        });
    }
}

Gruss Tom
 
Hallo, danke für die schnelle Antwort. Ich werde mal schauen, wie ich das am Besten in das Hauptprojekt einbauen kann. Wenn es dennoch nicht klappen sollte, melde ich mich nochmal :)

Edit:

Ich habe nochmal eine Frage und zwar, warum folgendes nicht funktioniert:

Code:
public class Main
{
	public static void main(String[] args)
	{
		new Thread()
		{
			public void run()
			{
				SwingUtilities.invokeLater(new Runnable()
				{
					public void run()
				   	{
						JOptionPane pane = new JOptionPane(new Object[]{"test text"});
		        		  
						JDialog dialog = pane.createDialog(null, "test caption");
						dialog.setModal(false);
						dialog.pack();
						dialog.setVisible(true);
						
						try
						{
							Thread.sleep(3000);
						}
						catch(Exception e)
						{
							e.printStackTrace();
						}
						
						System.exit(0);			
				   	}
				});
			}
		}.start();
	}
}

Ich erstelle doch einen neuen Thread und den lasse ich dann schlafen. Der Thread hat doch dann nichts mit dem EDT zu tun. Der EDT sollte doch in der Lage sein, das Fenster trotzdem zu zeichnen. Tut er aber nicht.

Edit:

Ich glaube ich habe es jetzt gerafft. Ich dachte

Code:
try { Thread.sleep(1); }	catch(InterruptedException e) {}

würde den Thread schlafen legen, dann dem Thread die Chance geben, die nötigen Aufgaben zu verarbeiten wie zeichnen .. Input/Output und den danach wieder schlafen legen.
 
Zuletzt bearbeitet:
Also ich habe es hin und her probiert und es läuft auch gut mit Timern, ABER das Problem ist einfach:

Wenn ich einen anderen Thread aufrufe, in dem ich etwas machen will (sei es via Socket zu irgendwas connecten ..), muss ich mit dem Hauptprogramm irgendwie warten.

Das Problem im Moment ist einfach folgendes:

func_1();
func_2();

Wenn ich in func_1 einen Socket erstelle (in einem neuen Thread) und ich dann func_2() aufrufe, in dem der Socket dann gebraucht wird, der Socket aber noch nicht erstellt wurde (weil der andere Thread noch nicht so weit ist), muss ich im Hauptprogramm halt warten. Das Problem ist dann wie du oben schon angesprochen hast, dass das Fenster nicht neu gezeichnet wird, wenn ich Thread.sleep() benutze. Gibt es einen Weg auf etwas zu warten, aber dass das Fenster trotzdem gezeichnet wird also die Zeichenroutine aufgerufen wird (von mir aus auch manuell)?

Irgendwo muss ich ja warten in einer while(state != STATE_CONNECTED); Schleife (mit oder ohne sleep).
repaint() scheint nicht zu funktionieren. Wenns halt garnicht anders geht, friert das Programm halt für ein paar Sekunden ein. Kann ich dann auch nicht ändern, aber da ich jetzt schon bestimmt 15 Stunden in den dämlichen Dialog reingesteckt habe, wäre ein Erfolgserlebnis doch ganz schön =)

Wie gesagt, der Dialog würde gut funktionieren mit Timern, wobei ich so oder so das Problem habe, dass ich irgendwo so oder so warten muss.

Übrigens, das Dialogfenster besitzt eine Progressbar, also es ist animiert.

Edit: Mir ist gerade eingefallen, dass es doch funktionieren würde bei mir, denn ich rufe die 1. Funktion auf, wenn ich einen Button gedrückt habe und die 2. wenn ein anderer Button gedrückt wurde .. Dann kann ich beim Drücken des 2. Buttons halt schauen, ob bei der 1. Funktion alles gut gegangen ist. Naja, wäre aber trotzdem schön, wenn jemand eine Idee hätte, wie man vernünftig warten kann, ohne dass das Programm einfriert. Ich weiß nicht, ob ich das noch brauchen werde, aber interessieren würde mich das alle Male.

Schonmal vielen Dank für das Lesen des Textes.
 
Zuletzt bearbeitet:
Zurück