JME2 -> JMECanvas and JInternalFrame problem

Hey,

I tried to use JInternalFrame and JMECanvas, but

effect is not really good, becouse when I fast relocate JInternalFrame canvas are

refreshing and it’s color change to white for miliseconds, when I relocate it slow all is good.

Must I use JMEDestkop to have JInternalFrame work properly?

Or should I better make my code?

This code is based on JMESwingTest, please help me:

[java]

package jmetest.util;



import java.awt.BorderLayout;

import java.awt.Dimension;

import java.awt.FlowLayout;

import java.awt.event.ActionEvent;

import java.awt.event.ComponentAdapter;

import java.awt.event.ComponentEvent;

import java.awt.event.KeyListener;

import java.awt.event.WindowEvent;

import java.util.logging.Level;

import java.util.logging.Logger;



import javax.swing.AbstractAction;

import javax.swing.JButton;

import javax.swing.JCheckBox;

import javax.swing.JDesktopPane;

import javax.swing.JFrame;

import javax.swing.JInternalFrame;

import javax.swing.JLabel;

import javax.swing.JPanel;

import javax.swing.JScrollPane;

import javax.swing.JToolBar;

import javax.swing.JTree;

import javax.swing.UIManager;



import com.jme.bounding.BoundingBox;

import com.jme.image.Texture;

import com.jme.input.InputHandler;

import com.jme.input.KeyInput;

import com.jme.input.action.InputAction;

import com.jme.input.action.InputActionEvent;

import com.jme.math.FastMath;

import com.jme.math.Quaternion;

import com.jme.math.Vector3f;

import com.jme.renderer.Renderer;

import com.jme.scene.shape.Box;

import com.jme.scene.state.TextureState;

import com.jme.system.DisplaySystem;

import com.jme.system.canvas.JMECanvas;

import com.jme.system.canvas.JMECanvasImplementor;

import com.jme.system.canvas.SimpleCanvasImpl;

import com.jme.system.lwjgl.LWJGLSystemProvider;

import com.jme.util.TextureManager;

import com.jmex.awt.input.AWTMouseInput;

import com.jmex.awt.lwjgl.LWJGLAWTCanvasConstructor;

import com.jmex.awt.lwjgl.LWJGLCanvas;







public class JMESwingTest {

private static final Logger logger = Logger.getLogger(JMESwingTest.class

.getName());



int width = 640, height = 480;



// Swing frame

private SwingFrame frame;



public JMESwingTest() {

frame = new SwingFrame();

// center the frame

frame.setLocationRelativeTo(null);

// show frame

frame.setVisible(true);

}



/**

  • Main Entry point…

    *
  • @param args
  •        String[]<br />
    

*/

public static void main(String[] args) {



try {

UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

} catch (Exception e) {

logger.logp(Level.SEVERE, JMESwingTest.class.toString(),

"main(args)", "Exception", e);

}

new JMESwingTest();

}



// **************** SWING FRAME ****************



// Our custom Swing frame… Nothing really special here.

class SwingFrame extends JFrame {

private static final long serialVersionUID = 1L;



// JPanel contentPane;

JPanel mainPanel = new JPanel();

LWJGLCanvas canvas = null;

JButton coolButton = new JButton();

JButton uncoolButton = new JButton();

JPanel spPanel = new JPanel();

JScrollPane scrollPane = new JScrollPane();

JTree jTree1 = new JTree();

JCheckBox scaleBox = new JCheckBox("Scale GL Image");

JPanel colorPanel = new JPanel();

JLabel colorLabel = new JLabel("BG Color:");



JMECanvasImplementor impl;

JDesktopPane desktop;

int frameCount = 0;



// Construct the frame

public SwingFrame() {



super();

desktop = new JDesktopPane();

JToolBar tb = new JToolBar();

tb.add(new AbstractAction("Add internal frame") {

@Override

public void actionPerformed(ActionEvent event) {

addInternalFrame();

}

});



getContentPane().add(tb, BorderLayout.NORTH);

tb.setFloatable(false);

getContentPane().add(desktop);

setDefaultCloseOperation(DISPOSE_ON_CLOSE);

setTitle("Test");

pack();

setLocationRelativeTo(null);

setVisible(true);

Dimension panelSize = desktop.getSize();

init();

mainPanel.setSize(panelSize);

desktop.add(mainPanel);





pack();

}



private void addInternalFrame() {

JInternalFrame frame = new JInternalFrame("Frame " + frameCount, true,

true, true, true);

frame.getContentPane().setLayout(new FlowLayout());

frame.getContentPane().add(new JLabel("Frame " + frameCount));

frame.pack();

frame.setLocation(200, 100);

frame.setSize(new Dimension(200,100));

frame.setVisible(true);

desktop.add(frame);



try {

frame.setSelected(true);

} catch (java.beans.PropertyVetoException exception) {

}



frameCount++;

}



@Override

public Dimension getPreferredSize() {

return new Dimension(600, 400);

}



// Component initialization

private void init() {



setTitle("JME - SWING INTEGRATION TEST");



//


GL STUFF

// make the canvas:
DisplaySystem display = DisplaySystem.getDisplaySystem(LWJGLSystemProvider.LWJGL_SYSTEM_IDENTIFIER);
display.registerCanvasConstructor("AWT", LWJGLAWTCanvasConstructor.class);
canvas = (LWJGLCanvas)display.createCanvas(width, height);
canvas.setUpdateInput(true);
canvas.setTargetRate(60);

// add a listener... if window is resized, we can do something about
// it.
canvas.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent ce) {
doResize();
}
});

// Setup key and mouse input
KeyInput.setProvider(KeyInput.INPUT_AWT);
KeyListener kl = (KeyListener) KeyInput.get();
canvas.addKeyListener(kl);
AWTMouseInput.setup(canvas, false);

// Important! Here is where we add the guts to the panel:
impl = new MyImplementor(width, height);
canvas.setImplementor(impl);

//
END OF GL STUFF
canvas.setBounds(0, 0, width, height);
mainPanel.add(canvas, BorderLayout.CENTER);
}

protected void doResize() {
if (scaleBox != null && scaleBox.isSelected()) {
impl.resizeCanvas(canvas.getWidth(), canvas.getHeight());
} else {
impl.resizeCanvas(width, height);
}
((JMECanvas)canvas).makeDirty();
}

// Overridden so we can exit when window is closed
@Override
protected void processWindowEvent(WindowEvent e) {
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING) {
System.exit(0);
}
}
}

// IMPLEMENTING THE SCENE:

class MyImplementor extends SimpleCanvasImpl {

private Quaternion rotQuat;
private float angle = 0;
private Vector3f axis;
private Box box;
long startTime = 0;
long fps = 0;
private InputHandler input;

public MyImplementor(int width, int height) {
super(width, height);
}

@Override
public void simpleSetup() {

// Normal Scene setup stuff...
rotQuat = new Quaternion();
axis = new Vector3f(1, 1, 0.5f);
axis.normalizeLocal();

Vector3f max = new Vector3f(5, 5, 5);
Vector3f min = new Vector3f(-5, -5, -5);

box = new Box("Box", min, max);
box.setModelBound(new BoundingBox());
box.updateModelBound();
box.setLocalTranslation(new Vector3f(0, 0, -10));
box.setRenderQueueMode(Renderer.QUEUE_SKIP);
rootNode.attachChild(box);

box.setRandomColors();

TextureState ts = renderer.createTextureState();
ts.setEnabled(true);
ts.setTexture(TextureManager.loadTexture(JMESwingTest.class
.getClassLoader().getResource(
"jmetest/data/images/Monkey.jpg"),
Texture.MinificationFilter.BilinearNearestMipMap,
Texture.MagnificationFilter.Bilinear));

rootNode.setRenderState(ts);
startTime = System.currentTimeMillis() + 5000;

input = new InputHandler();
input.addAction(new InputAction() {
@Override
public void performAction(InputActionEvent evt) {
logger.info(evt.getTriggerName());
}
}, InputHandler.DEVICE_MOUSE, InputHandler.BUTTON_ALL,
InputHandler.AXIS_NONE, false);

input.addAction(new InputAction() {
@Override
public void performAction(InputActionEvent evt) {
logger.info(evt.getTriggerName());
}
}, InputHandler.DEVICE_KEYBOARD, InputHandler.BUTTON_ALL,
InputHandler.AXIS_NONE, false);
}

@Override
public void simpleUpdate() {

if (KeyInput.get().isShiftDown())
{
System.out.println("shift is down");
}

input.update(tpf);

// Code for rotating the box... no surprises here.
if (tpf < 1) {
angle = angle + (tpf * 25);
if (angle > 360) {
angle = 0;
}
}
rotQuat.fromAngleNormalAxis(angle * FastMath.DEG_TO_RAD, axis);
box.setLocalRotation(rotQuat);

if (startTime > System.currentTimeMillis()) {
fps++;
} else {
long timeUsed = 5000 + (startTime - System.currentTimeMillis());
startTime = System.currentTimeMillis() + 5000;
logger.info(fps + " frames in " + (timeUsed / 1000f)
+ " seconds = " + (fps / (timeUsed / 1000f))
+ " FPS (average)");
fps = 0;
}
}
}


}

[/java]

I dont know, but generally I’d advise you not to use JMEDesktop as it has serious problems on osx and other platforms.

1 Like

Thanks for reply. Any ideas how can I make work this properly? I want to make model viewer which is based on JMECanvas and this is very important for me. Here is screen on which you can see my Viewer:

This looks like you just posted the jmetest code in the first post there… why? Anyway, my guess is that your problem is coming from mixing heavyweight (Canvas) and lightweight compoments (JInternalFrame)… These are the kinds of problems that would come up since the heavyweights always draw (or try to) over lightweight components.

Thats changed code from jmetest… look that I add toolbar with button which adds jinternalframe… do you have idea how make it work better?

If you run that and expand the window (GL isn’t scaling, so you’re able to see the white space around the canvas), you will see that the canvas is rendering over the JInternalFrames, which are just barely peeking out from the top edge of the scene. If you set the location of the frame being added, to somewhere not overlapping the LWJGL canvas, then the flickering doesn’t happen :slight_smile: (I just used the coordinates of x:700 y:100 when testing)

1 Like
sbook said:
If you run that and expand the window (GL isn't scaling, so you're able to see the white space around the canvas), you will see that the canvas is rendering over the JInternalFrames, which are just barely peeking out from the top edge of the scene. If you set the location of the frame being added, to somewhere not overlapping the LWJGL canvas, then the flickering doesn't happen :) (I just used the coordinates of x:700 y:100 when testing)


Thanks for reply. So what should I do to make it work properly?

I just gave it away above! Change the location of the JInternalFrame. In that function you wrote to add the frames, its putting them all at 200,100 which is right under the jME scene, so put them somewhere else :wink:

sbook said:
I just gave it away above! Change the location of the JInternalFrame. In that function you wrote to add the frames, its putting them all at 200,100 which is right under the jME scene, so put them somewhere else ;)


I think that you don’t understand what I want:) Problem is that I want to have JInternal frame above LWJGL Canvas, like here:

this is screenshot make for jmetest.swingui.TestJMEDesktopState.java

Right, this is using JMEDesktop however, which as Normen noted is not advisable due to stability issues. The only way you’re going to get a JInternalFrame to appear as if its rendering above a canvas is by using JMEDesktop (which essentially turns the JDesktopPane into a texture that is placed on a quad)

I make that screenshot only for example which show what I want to have. So only way is bad way becouse JMEDesktop sucks?

wonderk1d said:
I make that screenshot only for example which show what I want to have. So only way is bad way becouse JMEDesktop sucks?


Well I hate to use the word sucks.. perhaps 'needs improvement'? There are, however, windowing toolkits such as NiftyGUI, GBUI, and FengGUI which give GUI functionality that is a part of the GL context. (GBUI and FengGUI strive to provide features that are likely closer to what you're looking for)