Callable from swing elemnts

Hi all,

I just discovered jME and it looks like just the thing I was after.

I’m looking into mixing jME with Swing GUI.



I followed the tutorial and all worked well, managed to get the jME and Swing GUI in one JFrame, so I moved on to the next thing, trying to control the speed of rotation (from the simpleUpdate loop tutorial) using JButtons from the GUI, that’s when things stopped working.



Nothing happens as I click the button (i’m using addActionListener). I’m guessing because of threading issues and stuff. I have no idea how to use callables within a JButton. I’d appreciate if someone could walk me thru this.

this is my code:

[java]package test1;



import java.awt.Dimension;

import java.awt.EventQueue;

import java.awt.FlowLayout;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;



import javax.swing.JButton;

import javax.swing.JFrame;

import javax.swing.JPanel;



import com.jme3.app.SimpleApplication;

import com.jme3.material.Material;

import com.jme3.math.ColorRGBA;

import com.jme3.math.Vector3f;

import com.jme3.scene.Geometry;

import com.jme3.scene.shape.Box;

import com.jme3.system.AppSettings;

import com.jme3.system.JmeCanvasContext;



/**

  • Sample 2 - How to use nodes as handles to manipulate objects in the scene.
  • You can rotate, translate, and scale objects by manipulating their parent
  • nodes. The Root Node is special: Only what is attached to the Root Node
  • appears in the scene.

    */

    public class SwingCanvasTest extends SimpleApplication {

    private Geometry geom;

    private static float rotate = 2.0f;



    public static void main(String[] args) {

    EventQueue.invokeLater(new Runnable() {



    @Override

    public void run() {

    AppSettings settings = new AppSettings(true);

    settings.setHeight(480);

    settings.setWidth(640);

    SwingCanvasTest canvasApp = new SwingCanvasTest();

    canvasApp.setSettings(settings);

    canvasApp.createCanvas();

    JmeCanvasContext ctx = (JmeCanvasContext) canvasApp

    .getContext();

    ctx.setSystemListener(canvasApp);

    Dimension dim = new Dimension(640, 480);

    ctx.getCanvas().setPreferredSize(dim);



    JFrame window = new JFrame(“Swing App”);

    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    JPanel panel = new JPanel(new FlowLayout());

    final JButton faster = new JButton(“Faster”);

    faster.addActionListener(new ActionListener() {



    @Override

    public void actionPerformed(ActionEvent arg0) {

    rotate +=0.1f;

    }

    });

    panel.add(faster);

    final JButton slower = new JButton(“Slower”);

    faster.addActionListener(new ActionListener() {



    @Override

    public void actionPerformed(ActionEvent arg0) {

    rotate -=0.1f;

    }

    });

    panel.add(slower);

    panel.add(ctx.getCanvas());



    window.add(panel);

    window.pack();

    window.setVisible(true);

    canvasApp.startCanvas();

    }

    });

    }



    @Override

    public void simpleInitApp() {

    flyCam.setDragToRotate(true);



    Box b = new Box(Vector3f.ZERO, 1, 1, 1); // create cube shape at the

    // origin

    geom = new Geometry(“Box”, b); // create cube geometry from the shape

    Material mat = new Material(assetManager,

    “Common/MatDefs/Misc/Unshaded.j3md”); // create a simple

    // material

    mat.setColor(“Color”, ColorRGBA.Blue); // set color of material to blue

    geom.setMaterial(mat); // set the cube’s material

    rootNode.attachChild(geom);

    }



    @Override

    public void simpleUpdate(float tpf) {

    geom.rotate(0, rotate * tpf, 0);

    System.out.println(rotate);

    }

    }[/java]



    If anyone could help me with this, how to get Swing objects to manipulate the jME OpenGL canvas itself.

    Thanks alot!

any jme stuff, do it like you normally would but wrap it in a callable

[java]app.enqueue(new Callable<Void>() {

//modify scene graph

});[/java]



or w/e the syntax is :stuck_out_tongue:

thanks,

however i’m still not quite sure how to use it to implement on my code.



i have the method:

[java] @Override

public void simpleUpdate(float tpf) {

geom.rotate(0, rotate * tpf, 0);

System.out.println(rotate);

}[/java]



and want to change the speed of rotation (i.e, the rotate variable which is currently a static field)

I understand i need to do something like this:

[java]faster.addActionListener(new ActionListener() {



@Override

public void actionPerformed(ActionEvent arg0) {

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



@Override

public Void call() throws Exception {

*******

return null;

}



});

}

});[/java]



but what goes instead of the ***** to change the speed of rotation?

thanks, and I apologize if it’s something stupid which I simply don’t see now.

ah so your trying to share the same variable between threads. I’m not so good at threads myself, but i think you may need to look at synchronizing them, as there isn’t an Atomic equivalent.



http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html



someone better at multithreading should be able to help you more though :slight_smile:

I wouldn’t mind doing it in a different way, if uve got a better option

apparently you can emulate an AtomicFloat like this:

http://stackoverflow.com/questions/5505460/java-is-there-no-atomicfloat-or-atomicdouble



Using Atomic makes multithreading a whole lot easier, but like i say i don’t really use multithreading often, so theres probably a better way

Well, it kinda works…

I mean, it sometimes works, but sometimes nothing happens…



thanks though…

you calling the set and get methods?

yes, of course.

[java] rotate.set(rotate.get()+1.1f);

[/java]



tried inside the callable, outside the callable… sometimes works, sometimes nothing happens

grrr, not sure then, sorry :frowning: hopefully someone better can answer this, good luck

appreciate ur help.

thanks



final JButton slower = new JButton(“Slower”);

faster.addActionListener(new ActionListener() {



Lol, thats why.

damn copy & paste…

it works now using the atomic float…

thanks both of you.

@lablabla said:
damn copy & paste...
it works now using the atomic float..
thanks both of you.

It works ether way :P
You don't need synchronization, the update loop gets the value asynchronously when he needs it.

blah knew it would be something more simple :P, nice catch.

Don’t judge me as I clearly state I’m a multithreading newb :stuck_out_tongue:

@Setekh said:
It works ether way :P
You don't need synchronization, the update loop gets the value asynchronously when he needs it.


Which code are you looking at?

The one I saw was sharing an unsynchronized non-atomic static variable. This means that if you are on a multi-core system that one thread could see changes to that value very late because there is no memory barrier forcing a refresh of the thread's local cache. (basically)
2 Likes

You could achieve the same thing by either marking the variable as volatile or by passing it into the enqueued task as a local variable. Making it atomic also works though so you have a few options :slight_smile:

1 Like
@zarch said:
You could achieve the same thing by either marking the variable as volatile or by passing it into the enqueued task as a local variable. Making it atomic also works though so you have a few options :)


Yeah, I usually recommend the atomics over volatile just because they are more flexible and require slightly less explanation. :) The atomics are nice because you can do test-and-set style operations which frequently come up.
1 Like

@pspeed

I was talking about the update loop, not how he coded it. Tho thank you for enlightening me, i would of use volatile but really if i was faced with the issue i couldn’t explain it :stuck_out_tongue:

@Setekh said:
@pspeed
I was talking about the update loop, not how he coded it. Tho thank you for enlightening me, i would of use volatile but really if i was faced with the issue i couldn't explain it :P


I learned more than I ever wanted to know about Java's threading model back before JDK 1.5 when "double checked locking" was impossible to implement (volatile had no real semantic meaning prior to 1.5). Reading and re-reading those articles provided lots of interesting info on the underbelly of the threading model. Reading anything from Doug Lea or going through the source for the concurrent package is also very educational.