Hi guys,
I am following the method JME3 Canvas in a Swing GUI. I would like to have this embedding into a JFrame so that I can resize the JMonkey display interactively, and add some custom Swing gui stuff. I am combining this technique with a custom software cursor (attach stuff to guiNode). So, I would like to hide the original operating system cursor when moving the mouse over the JMonkey display (but not over my Swing stuff). I have tried many things, but it does not seem to work. Here is my best attempt so far:
[java]
import com.jme3.app.SimpleApplication;
import com.jme3.font.BitmapText;
import com.jme3.input.RawInputListener;
import com.jme3.input.event.JoyAxisEvent;
import com.jme3.input.event.JoyButtonEvent;
import com.jme3.input.event.KeyInputEvent;
import com.jme3.input.event.MouseButtonEvent;
import com.jme3.input.event.MouseMotionEvent;
import com.jme3.input.event.TouchEvent;
import com.jme3.system.AppSettings;
import com.jme3.system.JmeCanvasContext;
import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Cursor;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
/**
*
-
Based on jme3test.awt.TestCanvas
-
@author
*/
public class MyWindow1 extends SimpleApplication implements RawInputListener {private Canvas canvas;
private JFrame frame;
private JPanel mainPanel;
private BitmapText cursor;
//------------------------------
private Cursor blankCursor;public MyWindow1() {
AppSettings mySettings = new AppSettings(true); mySettings.setWidth(640); mySettings.setHeight(480); mySettings.setVSync(true); // reduces my computer's noise this.setSettings(mySettings); this.createCanvas(); JmeCanvasContext myContext = (JmeCanvasContext) this.getContext(); canvas = myContext.getCanvas(); canvas.setSize(mySettings.getWidth(), mySettings.getHeight()); frame = new JFrame("My Window"); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); frame.addWindowListener(new WindowAdapter() { @Override public void windowClosed(WindowEvent e) { MyWindow1.this.stop(); } }); mainPanel = new JPanel(); mainPanel.setLayout(new BorderLayout()); frame.getContentPane().add(mainPanel); mainPanel.add(canvas, BorderLayout.CENTER); frame.pack(); //--------------------------------------------- JButton button = new JButton("Hello"); mainPanel.add(button, BorderLayout.SOUTH); // Transparent 16 x 16 pixel cursor image. BufferedImage cursorImg = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB); // Create a new blank cursor. blankCursor = Toolkit.getDefaultToolkit().createCustomCursor( cursorImg, new Point(0, 0), "blank cursor"); frame.setCursor(blankCursor); mainPanel.setCursor(blankCursor); canvas.setCursor(blankCursor);
}
private void startEverything() {
this.startCanvas();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}@Override
public void simpleInitApp() {
super.inputManager.update(1.0f);
// Disable fly cam
//stateManager.detach(stateManager.getState(FlyCamAppState.class));
flyCam.setEnabled(false);// Cursor guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt"); cursor = new BitmapText(guiFont, false); cursor.setSize(guiFont.getCharSet().getRenderedSize()); cursor.setText("->"); cursor.setLocalTranslation(0, 0, 0); guiNode.attachChild(cursor); inputManager.addRawInputListener(this); inputManager.setCursorVisible(false);
}
@Override
public void simpleUpdate(float tpf) {
}public static void main(String[] args) {
final MyWindow1 m = new MyWindow1(); try { Thread.sleep(500); } catch (InterruptedException ex) { } SwingUtilities.invokeLater(new Runnable() { public void run() { m.startEverything(); } });
}
@Override
public void beginInput() {
}@Override
public void endInput() {
}@Override
public void onJoyAxisEvent(JoyAxisEvent evt) {
}@Override
public void onJoyButtonEvent(JoyButtonEvent evt) {
}@Override
public void onMouseMotionEvent(MouseMotionEvent evt) {
cursor.setLocalTranslation(inputManager.getCursorPosition().getX(), inputManager.getCursorPosition().getY(), 0);
}@Override
public void onMouseButtonEvent(MouseButtonEvent evt) {
System.out.println(“Mouse button event”);
}@Override
public void onKeyEvent(KeyInputEvent evt) {
}@Override
public void onTouchEvent(TouchEvent evt) {
}
}
[/java]
As you can see, I have called inputManager.setCursorVisible(false). Moreover, I am also setting a blank cursor on the JFrame, and the panels (including the canvas), using standard AWT methods.
But I guess there is something going on here that is specific to the Swing embedding. Indeed, if I try to change the operating system cursor image with (inside simpleInitApp)
[java]
inputManager.setCursorVisible(true);
assetManager.registerLocator(“assets”, FileLocator.class);
inputManager.setMouseCursor((JmeCursor)assetManager.loadAsset(“cursor.ico”));
[/java]
(where cursor.ico is a valid icon file that can be found), then I get an LWJGL exception (array index out of bounds). Perhaps the mouse is not yet initialized, which could also explain why the part “inputManager.setCursorVisible(false)” fails. Could someone shed some light on this?
Thanks!
Tom