Question about Callables and jME

Guys, I am embarrassed asking this question as I’ve been using jME for a while but it’s really more of a Java question maybe not sure.



I have a callable that gets triggered on action listener whenever user clicks a certain button during the game. So when this button is clicked the following code is triggered:



[java]

myApp.getInputManager().addMapping(“jumpTime”, new KeyTrigger(KeyInput.KEY_J));







if (name.equals(“jumpTime”) && keyPressed) {

exec.submit(jumpTime);

}







/** Jump time Callable. Allows user to jump

  • in time during the animation (forward/backward)

    */

    Callable jumpTime = new Callable() {



    public Object call() throws Exception {

    try {



    //setPauseOnLostFocus(false);

    final float value = Float.parseFloat(JOptionPane.showInputDialog(null,

    “Enter Time”,

    “Choose Desired Jump Time”,

    JOptionPane.QUESTION_MESSAGE));





    myApp.enqueue(new Callable<Void>() {



    public Void call() throws Exception {

    cinematic.setTime(value);

    System.out.println("Jumping to time: "+cinematic.getTime());

    return null;

    }

    });



    } catch (Exception nFE) {

    // do nothing just cancel command

    System.out.println(“Exception: Jumping in time failed”);

    }

    return null;

    }

    };



    [/java]





    The issue is that for some reason the JOptionPane window appears behind the jME window and not above it which didn’t used to happen before and I can’t figure out why. All dialogs windows are modal by default so I dont’ udnerstand why this is happening.

It doesn’t matter if it’s modal or not because the owner is not the JME window. Modality only controls how events are delivered but a confluence of events can happen such that the JME window gets focus and then the JOptionPane will be behind it. And then there is little you can do about it, though sometimes alt-tabbing away and back can fix it.



You can potentially mitigate this issue by using SwingUtilities.invokeLater() to pop-up the JOptionPane. It will at least decrease the cases where the pop-up gets hidden.



Other than getting a proper owner, the only other way is to create a dialog that is setup to be “always on top”… and that’s not as straight-forward as your JOptionPane call though there might still be a way to use JOptionPane to do it.

Also, I’m curious… what is “exec” and why are you running the JOptionPane part in a callable using it? I would have thought executing it on the Swing thread would be more appropriate.

exec is:



[java] private ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(2);[/java]



I am using Cineamtics running and animation and wanted to trigger a window to specify a jump to a certain time on the fly while running the animation. If I don’t use a Callable (which makes it work just fine) the animation time won’t pause and will mess up my sequence of events so I used a callable as suggested by one of the developers here.

Yeah, you are pretty much screwed if you can’t pause the animation any other way than a bunch of chained event blocking. I thought animation could be paused at least.



At any rate, you shouldn’t ever interact with Swing on a thread other than the AWT thread. You could use SwingUtilities.invokeAndWait() but I suspect you will create a deadlock situation.



A real application that wanted to pause the animation would pause the animation. Then it would prompt the user on the swing thread. Then it would set the new time and let the animation run again. All as asynchronously as possible. Relying on blocking hacks to achieve this is dangerous.

How about just passing 0 for tpf in simpleUpdate when paused? (modify the SimpleApplicatrion calss to your needs/ fork it)

Not sure how that would solve the problem?

Note that it only does that with Eclips it does not do that with the SDK

@garnaout said:
Not sure how that would solve the problem?


You are fake-pausing animation by blocking the rendering thread. We were suggesting changes that would let you _actually_ pause the animation so that you wouldn't have to fake-pause it.

This would let you use more straight-forward approaches instead of a nineteen-layer deep Rube-Goldberg blocking strategy that requires lots of chanting and finger crossing.

Mostly, it would let you do swing on the swing thread... since anything else is scary.

But why does it work seamlessly on the SDK then? it only does that with Eclipse!

Because wrong threading causes funny issues. Race conditions etc.

And probably because Netbeans uses Swing and Eclipse doesn’t… it will aggravate any threading issues differently.

1 Like

hmmmm I see. So without using an approach where I have to fork the simpleApplication, what would be the right way to initiate a window that takes the user input from jME without jeopardizing the thread safety. What’s the right way to do this without having the implement some dirty hacks?

I don’t even know what you are talking about anymore. No one ever suggested forking simple application.



I don’t understand why you can’t use swing on the swing thread by using SwingUtilities.invokeLater().



These conversations are exhausting.

How about just passing 0 for tpf in simpleUpdate when paused? (modify the SimpleApplicatrion calss to your needs/ fork it)


I did , and got the same issue
@garnaout said:
I did , and got the same issue


If that was the only thing you changed then of course you will get the same issue since that wasn't to fix the issue... that was to pause the animation.

You must do swing on the swing thread.
1 Like

I am not in expert in this but if you are using:



[java] final float value = Float.parseFloat(JOptionPane.showInputDialog(null,

“Enter Time”,

“Choose Desired Jump Time”,

JOptionPane.QUESTION_MESSAGE));[/java]



the null is the parent of the dialog optionPane, why don’t you pass the parent frame component of the jME window to it? wouldn’t that solve it?

No, just listen to pspeed :roll: Swing and jME3 are very similar in how you have to account for their thread.

http://docs.oracle.com/javase/tutorial/uiswing/concurrency/

1 Like
You must do swing on the swing thread.


what do you mean?

I did this and still the window appear in the back. What else should I do? also @nightwolf911 has a point , why can't we just pass the parent component of the jME window, I know you guys are right but I am just interested to know why his approach is wrong (out of curiosity)

[java] else if (name.equals("jumpTime") && keyPressed) {

// intended to execute a new runnable thread from a Swing application
// without disturbing the normal sequence of event dispatching from the GUI
SwingUtilities.invokeLater(
new Runnable(){
public void run(){
final float value = Float.parseFloat(JOptionPane.showInputDialog(null,
"Enter Time",
"Choose Desired Jump Time",
JOptionPane.QUESTION_MESSAGE));
}
}
);[/java]

It is also a good idea to pass the parent.



I just couldn’t get past the badness of doing swing on a non-swing thread. It’s like Swing 101 “Things never to do”.

1 Like