[SOLVED] JME only renders within two-thirds of the Swing Canvas

I’m trying to render a JME within a Swing Canvas. All seems well, except JME only renders within two-thirds of the canvas on both axis.

I initially thought that the Canvas was not taking up the full size of the window, but upon changing the canvas background color to magenta, it would seem the canvas is occupying the whole window.

The ‘padding’ around JME always seems to be one-third of the size (on both axis), despite resizing the window etc.

If anyone could please let me know what I’m missing, or steer me in the right direction I’d greatly appreciate it.

Here’s the code:

import com.jme3.app.SimpleApplication;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;
import com.jme3.system.AppSettings;
import com.jme3.system.JmeCanvasContext;

import java.awt.*;
import javax.swing.*;

public class CanvasIssue {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            AppSettings settings = new AppSettings(true);
            settings.setWidth(500);
            settings.setHeight(500);

            SimpleGame app = new SimpleGame();
            app.setShowSettings(false);
            app.setSettings(settings);
            app.createCanvas();

            JmeCanvasContext ctx = (JmeCanvasContext) app.getContext();
            ctx.setSystemListener(app);
            Canvas canvas = ctx.getCanvas();
            ctx.getCanvas().setPreferredSize(new Dimension(settings.getWidth(), settings.getHeight()));
            canvas.setBackground(Color.MAGENTA);

            JPanel panel = new JPanel(new BorderLayout());
            panel.add(canvas, BorderLayout.CENTER);

            JFrame window = new JFrame("Swing Application");
            window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            window.getContentPane().setLayout(new BorderLayout());
            window.getContentPane().add(panel, BorderLayout.CENTER);
            window.pack();
            window.setVisible(true);

            app.startCanvas();
        });
    }

    private static class SimpleGame extends SimpleApplication {

        private Geometry boxGeom;
        @Override
        public void simpleInitApp() {
            flyCam.setDragToRotate(true);
            Box b = new Box(1, 1, 1);
            boxGeom = new Geometry("Box", b);
            Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
            mat.setTexture("ColorMap", assetManager.loadTexture("Interface/Logo/Monkey.jpg"));
            boxGeom.setMaterial(mat);
            rootNode.attachChild(boxGeom);
            viewPort.setBackgroundColor(ColorRGBA.fromRGBA255(135, 206, 235, 1));
        }
        @Override
        public void simpleUpdate(float tpf) {
            boxGeom.rotate(tpf, tpf, tpf);
        }
    }
}

I can’t reproduce on ubuntu, do you use high dpi/display scaling settings on your OS?

1 Like

Thanks mate.

Windows scaling seems to be the culprit :frowning:
Setting scaling to 100% in Windows display settings solved the problem.

Was using 150% scaling before.

Guessing this is my issue after all.
https://github.com/jMonkeyEngine/jmonkeyengine/issues/1393

Cheers.

1 Like

Fixed code for Windows below… only a workaround but not half bad.

Custom JPanel does the trick, scaling the canvas up by the Windows scaling factor.

public class CanvasIssue {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            AppSettings settings = new AppSettings(true);
            settings.setWidth(500);
            settings.setHeight(500);

            SimpleGame app = new SimpleGame();
            app.setShowSettings(false);
            app.setSettings(settings);
            app.createCanvas();

            JmeCanvasContext ctx = (JmeCanvasContext) app.getContext();
            ctx.setSystemListener(app);
            Canvas canvas = ctx.getCanvas();
            ctx.getCanvas().setPreferredSize(new Dimension(settings.getWidth(), settings.getHeight()));
            canvas.setBackground(Color.MAGENTA);

            JFrame window = new JFrame("Swing Application");


            // FIX: Custom panel to correct for Windows OS display scaling.
                // If you have scaling set to something different from 100% in Windows display settings, the canvas will render at the incorrect size.
                // This fixes this issue, by scaling the canvas bounds by the Windows scaling amount.
            JPanel panel = new JPanel(new BorderLayout()) {
                @Override
                public void doLayout() {
                    if (JmeSystem.getPlatform().getOs() == Platform.Os.Windows) {
                        GraphicsConfiguration graphicsConfiguration = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
                        AffineTransform displayTransform = graphicsConfiguration.getDefaultTransform();
                        double scaleX = displayTransform.getScaleX(); // Windows OS Display X scaling.
                        double scaleY = displayTransform.getScaleY(); // Windows OS Display Y scaling.
                        canvas.setBounds(0, 0, (int)(getWidth() * scaleX), (int)(getHeight() * scaleY));
                    }

                }
            };
            panel.add(canvas, BorderLayout.CENTER);


            window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            window.getContentPane().setLayout(new BorderLayout());
            window.getContentPane().add(panel, BorderLayout.CENTER);
            window.pack();
            window.setVisible(true);

            app.startCanvas();
        });
    }

    private static class SimpleGame extends SimpleApplication {

        private Geometry boxGeom;
        @Override
        public void simpleInitApp() {
            flyCam.setDragToRotate(true);
            Box b = new Box(1, 1, 1);
            boxGeom = new Geometry("Box", b);
            Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
            mat.setTexture("ColorMap", assetManager.loadTexture("Interface/Logo/Monkey.jpg"));
            boxGeom.setMaterial(mat);
            rootNode.attachChild(boxGeom);
            viewPort.setBackgroundColor(ColorRGBA.fromRGBA255(135, 206, 235, 1));
        }
        @Override
        public void simpleUpdate(float tpf) {
            boxGeom.rotate(tpf, tpf, tpf);
        }
    }

}
3 Likes