Search code examples
javamultithreadingjoptionpane

JOptionPane displays a blank window


I'm currently developing a online version of the game ludo.

The server a client connects to sends a command if enough players connected to notify every client that the game will start.

I want to achieve that a JOptionPane is displayed on the client side that says something like "Waiting for game start" and then continues to wait for a new Input by the server.

At first my code looked like this:

ImageIcon icon = new ImageIcon(getClass().getResource("/resources/waiting.gif"));
JOptionPane.showMessageDialog(null, "Waiting for game start",
             "Please Wait",JOptionPane.INFORMATION_MESSAGE, icon);
command = (String) in.readObject();

This worked in so far that the JOptionPane was displayed. Problem: The code got interrupted until the client pressed ok. Then the window was gone and the program waited. So that wasn't what I wanted to achieve.

So I tried to run the JOptionPane in it's own thread and close the Thread when a message was received. This looks like this:

Thread t = new Thread(new Runnable(){
    public void run(){
        synchronized(this){
            ImageIcon icon = new ImageIcon(getClass().getResource("/resources/waiting.gif"));
            JOptionPane.showMessageDialog(null, "Waiting for game start",
             "Please Wait",JOptionPane.INFORMATION_MESSAGE, icon);
        }
    }  
});
t.start();
command = (String) in.readObject();
t.interrupt();

This solved the problem that the code beneath the JOptionPane wasn't executed but running the code like this displayed the JOptionPane as a blank window with a title. Screenshot below...

https://i.sstatic.net/2W42B.png

So my question is: How can I solve this problem or is there any other way to display a JOptionPane without stoping code execution?


Solution

  • The JOptionPane class is, like most of Swing, not thread-safe. Calling showMessageDialog() should only be done from the EDT. The EDT should itself be used only for GUI components and sometimes small tasks, and any heavy processing should be done in background threads.

    Now as for your code:

    • You create a GUI component outside the EDT
    • You do heavy processing on the EDT afterwards, which does not allow Swing to repaint your component (I imagine that is the problem here)
    • You then call interrupt on a thread that doesn't really do anything anyway. Interrupting it is not going to make the message go away.

    A much better way of achieving what seems to be your goal is to use a SwingWorker. Create a message JFrame with a message or a progress bar or what not, show it, then start a SwingWorker that will do the processing and when done - will hide you JFrame.