Properties dialog problem

I'm launching my application, which is derived from SimpleGame, from a swing interface, in a new Thread (with the overloaded run() doing the starting).



If I try to show the properties box (via setConfigShowMode(ConfigShowMode.AlwaysShow) ), everything hangs.



I think I've located the issue, but my limited knowledge in concurrency wasn't enough to fix it (and I have tried  :// ). The hang occurs when creating an LWJGLPropertiesDialog object:



// from com.jme.system.lwjgl.LWJGLPropertiesDialog
    public LWJGLPropertiesDialog(GameSettings source, URL imageFile, Stack<Runnable> mainThreadTasks) {
        if (null == source)
            throw new JmeException("PropertyIO source cannot be null");

        this.source = source;
        this.imageFile = imageFile;
        this.mainThreadTasks = mainThreadTasks;

        ModesRetriever retrieval = new ModesRetriever(); // A runnable object
        if ( mainThreadTasks != null )
        {
            mainThreadTasks.add(retrieval);
        }
        else
        {
            retrieval.run();
        }
        modes = retrieval.getModes();
        Arrays.sort(modes, new DisplayModeSorter());
       
        createUI();
    }



This is called from AbstractGame's getAttributes method, and the mainThreadTasks stack is not null. So the retrieval task is added to the stack, and then retrieval.getModes() is called, which is what hangs:


// from com.jme.system.lwjgl.LWJGLPropertiesDialog.ModesRetriever
        public DisplayMode[] getModes() {
            while (!this.ready) {
                try {
                    Thread.sleep(10);
                } catch (Exception e) { }
            }
            return modes;
        }



The "ready" variable was supposed to be set to true by the following piece of code:


// from com.jme.system.lwjgl.LWJGLPropertiesDialog.ModesRetriever
        public void run() {
            try {
                modes  = Display.getAvailableDisplayModes();
            } catch (LWJGLException e) {
                logger.logp(Level.SEVERE, this.getClass().toString(),
                        "LWJGLPropertiesDialog(GameSettings, URL)", "Exception", e);
                return;
            }
            ready = true;
        }



which is never actually being run (AbstractGame would have called this later, but the application never gets past the retrieval.getModes() line, so AbstractGame never gets around to it). So I guess the problem is sort of that AbstractGame expects the object to finish constructing, but that can only be done when AbstractGame starts running Runnables from the stack  :-o (I tried to make a little post-initialization method with the last 3 lines from the constructor, and calling it from AbstractGame after it starts running the mainThreadTasks; this got a window on screen that wouldn't update and showed no controls; this is where I got really confused, and figured I didn't know enough to fix this).

If a small test is needed to verify, I'll make one later, though I think the code sort of gives away that there is in fact a problem.

I've currently coded around this by setting setConfigShowMode(ConfigShowMode.NeverShow), creating an LWJGLPropertiesDialog, and adding a listener to it that opens my application when the properties window closes (via "ok").

So perhaps someone with more knowledge in concurrency is willing to take a shot a this...

A simple test would be the fastest way to help you out, if you don't mind.

Woah, sorry I didn't notice the reply. I was thinking of catching the reply in the forum's RSS, and must have missed it by accident.



I had another separate issue, and was searching the forum for whether it had been brought up before posting, and found this post.



The test case for my two issues is pretty much identical (the other issue is http://www.jmonkeyengine.com/jmeforum/index.php?topic=10987.0); Here it is, a simple game and a launcher for the game which attempts to show the properties dialog:



import com.jme.app.SimpleGame;
import com.jme.math.Vector3f;
import com.jme.scene.shape.Box;

public class SimpleTest extends SimpleGame
{
   @Override
   protected void simpleInitGame()
   {
      rootNode.attachChild(new Box("", Vector3f.ZERO, 5,5,5));      
   }    
}





import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;

import com.jme.app.AbstractGame.ConfigShowMode;


public class SimpleSwingLauncher extends JFrame
{
   public SimpleSwingLauncher()
   {
      JButton launcher = new JButton();
      
      ActionListener l = new ActionListener()
      {
         @Override
         public void actionPerformed(ActionEvent e)
         {
            SimpleTest test = new SimpleTest();
            test.setConfigShowMode(ConfigShowMode.AlwaysShow); // Application freezes!
            test.start();
         }         
      };
      
      launcher.addActionListener(l);      
      this.add(launcher);
   }
   
   
   public static void main(String[] args)
   {
      SimpleSwingLauncher slauncher = new SimpleSwingLauncher();
      slauncher.setSize(400, 400);      
      slauncher.setVisible(true);
   }
}

Hi!



I had exactly the same problem yesterday, and solved it with Wizems help (through PM), thanks again!! :slight_smile:

I hope this will help someone in the future, so I'll post my solution.



My fault was that I tried to start the "LWJGLPropertiesDialog" directly with Swing's Event-Thread ("AWT-EventQueue-0"). And "AbstractGame#getAttributes()" asks the following…

         final Stack<Runnable> mainThreadTasks = new Stack<Runnable>();
         try {
            if (EventQueue.isDispatchThread()) {
               dialogRef.set(new LWJGLPropertiesDialog(settings,
                     dialogImageRef, mainThreadTasks));
            } else {
               EventQueue.invokeLater(new Runnable() { public void run() {
                     dialogRef.set(new LWJGLPropertiesDialog(settings,
                           dialogImageRef, mainThreadTasks));
                  }
               });
            }
         } catch (Exception e) {
            logger.logp(Level.SEVERE, this.getClass().toString(),
                  "AbstractGame.getAttributes()", "Exception", e);
            return;
         }



...which leads to the EventQueue idling forever in "LWJGLPropertiesDialog$ModesRetriever#getModes()".

            public DisplayMode[] getModes() {
            while (!this.ready) {
                try {
                    Thread.sleep(10);
                } catch (Exception e) { }
            }
            return modes;



So I just modified my Swing-Action to something like this

         new Thread (new Runnable() {
            @Override
            public void run() {
               actionPerformed(e);
            }
         }).start();


... and it works! :)

Hope this helps someone save some time debugging! ;)