Hot questions for Using Lightweight Java Game Library in swing

Question:

I'm right now trying to mix LWJGL and Swing so I can have Swing's GUI and LWJGLS Graphics... But it doesn't work, Thanks in advance.

Code :

/**
 * 
 */
public static TSudioQE TSudio;
private static final long serialVersionUID = -8495077485468477943L;

public static void main(String[] args) {
    try {
        TSudioQE tsudio = new TSudioQE();
    } catch (LWJGLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

public TSudioQE() throws LWJGLException {
    setTitle("TSudio Quall Engine 1X");
    JPanel p = new JPanel();

    Canvas c = new Canvas();

    Display.create();
    Display.setParent(c);

    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);

    // set the color of the quad (R,G,B,A)
    GL11.glColor3f(0.5f, 0.5f, 1.0f);

    // draw quad
    GL11.glBegin(GL11.GL_QUADS);
    GL11.glVertex2f(100, 100);
    GL11.glVertex2f(100 + 200, 100);
    GL11.glVertex2f(100 + 200, 100 + 200);
    GL11.glVertex2f(100, 100 + 200);
    GL11.glEnd();
    add(p);
    setSize(800, 460);
    setExtendedState(JFrame.MAXIMIZED_BOTH);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

@Override
public void windowOpened(WindowEvent e) {
    // TODO Auto-generated method stub

}

@Override
public void windowClosing(WindowEvent e) {
    // TODO Auto-generated method stub

}

@Override
public void windowClosed(WindowEvent e) {
    // TODO Auto-generated method stub

}

@Override
public void windowIconified(WindowEvent e) {
    // TODO Auto-generated method stub

}

@Override
public void windowDeiconified(WindowEvent e) {
    // TODO Auto-generated method stub

}

@Override
public void windowActivated(WindowEvent e) {
    // TODO Auto-generated method stub

}

@Override
public void windowDeactivated(WindowEvent e) {
    // TODO Auto-generated method stub

}

I get the following error:

 org.lwjgl.LWJGLException: Parent.isDisplayable() must be true
at org.lwjgl.opengl.Display.createWindow(Display.java:301)
at org.lwjgl.opengl.Display.setParent(Display.java:451)
at qq.application.TSudioQE.<init>(TSudioQE.java:47)
at qq.application.TSudioQE.main(TSudioQE.java:33)

Anyone who know how to fix it? It could be nice.

Have a great day :-)


Answer:

The Canvas you set as parent for your Display has to be visible:

JFrame frame = new JFrame();
Canvas canvas = new Canvas();
frame.add(canvas);
frame.setVisible(true);
try 
{
    Display.setParent(canvas);
    Display.create();
} 
catch (LWJGLException e) 
{
    e.printStackTrace();
}

Question:

In my app, I have a class that acts as a Swing component to render a 3D window using LWJGL. When I go to run the app, I get the error from Display.create() that Parent.isDisplayable() must be true. I've tried looking, and most people say it happens when you call Display.create() before calling setVisible(). However, that's not the case here, and I can't seem to figure out why I'm getting the error.

My control looks like this:

public class WorldCanvas extends JPanel {
    private final Canvas canvas = new Canvas();

    public WorldCanvas() {
        ...
        add(canvas, BorderLayout.CENTER);

        try {
            Display.setParent(canvas);

            setVisible(true);
            canvas.setVisible(true);
            Display.create();
        } catch (LWJGLException e) {
            e.printStackTrace();
            return;
        }
    }
}

It's being added directly to a JFrame, and setVisible(true) is also called on the JFrame before this is added (however this error is being generated before it can even be added, given it's in the constructor). Why am I getting this error?


Answer:

You are trying to create the display in the constructor of the JPanel that holds your Canvas. So the Canvas is not displayable because its parent, the WorldCanvas, is not displayable as it is just about to be created.

You will have to move the initialization into a method called after the constructor.

Question:

I wanted to figure out what is difference between openGL(LWJGL) and swing when it comes to rendering simple squares. Unsurprisingly, openGL won, but at some tests the result was close, or even in favor to swing. Why is it so??

My test results:

Testing for a total of 500000 rectangles
Swing time: 0.16367821
OpenGL time: 0.06317429
OpenGL relative to SWING is faster by  159.0899%

Testing for a total of 750000 rectangles
OpenGL time: 0.066062525
Swing time: 0.16988374
OpenGL relative to SWING is faster by  157.156%

Testing for a total of 1000000 rectangles
OpenGL time: 0.0907693
Swing time: 0.15694521
OpenGL relative to SWING is faster by  72.90561%

Testing for a total of 1250000 rectangles
OpenGL time: 0.09591239
Swing time: 0.17011923
OpenGL relative to SWING is faster by  77.369385%

Testing for a total of 1500000 rectangles
OpenGL time: 0.11926948
Swing time: 0.21623997
OpenGL relative to SWING is faster by  81.303696%

Testing for a total of 1750000 rectangles
OpenGL time: 0.16327758
Swing time: 0.25741237
OpenGL relative to SWING is faster by  57.65323%

Testing for a total of 2000000 rectangles
OpenGL time: 0.17265266
Swing time: 0.2788536
OpenGL relative to SWING is faster by  61.511322%

Testing for a total of 2250000 rectangles
OpenGL time: 0.2492242
Swing time: 0.3022127
OpenGL relative to SWING is faster by  21.261368%

Testing for a total of 2500000 rectangles
Swing time: 0.3231118
OpenGL time: 0.29499054
OpenGL relative to SWING is faster by  9.532944%

Testing for a total of 2750000 rectangles
OpenGL time: 0.34329778
Swing time: 0.38381234
OpenGL relative to SWING is faster by  11.801575%

Testing for a total of 3000000 rectangles
OpenGL time: 0.34859535
Swing time: 0.39274055
OpenGL relative to SWING is faster by  12.663734%

Testing for a total of 3250000 rectangles
Swing time: 0.4241282
OpenGL time: 0.44056854
OpenGL relative to SWING is faster by  -3.7316208%

Testing for a total of 3500000 rectangles
Swing time: 0.4600469
OpenGL time: 0.4737318
OpenGL relative to SWING is faster by  -2.8887482%

Testing for a total of 3750000 rectangles
Swing time: 0.40855232
OpenGL time: 0.25052726
OpenGL relative to SWING is faster by  63.07698%

Testing for a total of 4000000 rectangles
Swing time: 0.5119725
OpenGL time: 0.55266017
OpenGL relative to SWING is faster by  -7.362152%

Testing for a total of 4250000 rectangles
OpenGL time: 0.5010328
Swing time: 0.57198834
OpenGL relative to SWING is faster by  14.16185%

Testing for a total of 4500000 rectangles
OpenGL time: 0.53123826
Swing time: 0.5992712
OpenGL relative to SWING is faster by  12.806473%

Testing for a total of 4750000 rectangles
OpenGL time: 0.5412617
Swing time: 0.6458795
OpenGL relative to SWING is faster by  19.328514%

Testing for a total of 5000000 rectangles
OpenGL time: 0.58324844
Swing time: 0.69343716
OpenGL relative to SWING is faster by  18.892242%

Code I was using:

package swingVSopengl;

import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import static org.lwjgl.opengl.GL11.*;

public class SwingVsOpenGL {

    static int amount = 0;
    static float swingtime, opengltime;

    public static void main(String[] args) {

        for (amount = 500000; amount <= 5000000; amount += 250000) {

            System.out.println("Testing for a total of "
                    + String.valueOf(amount) + " rectangles");
            new SwingWay();
            new OpenGLWay();
            System.out.println("OpenGL relative to SWING is faster by  "
                    + String.valueOf(swingtime / opengltime * 100 - 100) + "%");
            System.out.println();
        }

        System.exit(0);
    }

    private static class SwingWay extends JFrame {

        public SwingWay() {
            setSize(64, 64);
            add(new JPanel() {
                @Override
                public void paint(Graphics g) {
                    super.paint(g);
                    long time = System.nanoTime();
                    for (int i = 0; i < amount; i++) {
                        g.fillRect(0, 0, 16, 16);
                    }
                    swingtime = (float) (System.nanoTime() - time) / 1000000000;
                    System.out.print("Swing time: ");
                    System.out.println(swingtime);
                    dispose();
                }
            });
            setVisible(true);
        }

    }

    private static class OpenGLWay {
        OpenGLWay() {
            try {
                Display.setDisplayMode(new DisplayMode(64, 64));
                Display.setTitle("A fresh display!");
                Display.create();
            } catch (LWJGLException e) {
                e.printStackTrace();
                Display.destroy();
                System.exit(1);
            }

            glMatrixMode(GL_PROJECTION);
            glOrtho(0, 640, 480, 0, 1, -1);
            glMatrixMode(GL_MODELVIEW);

            long time = System.nanoTime();
            for (int i = 0; i < amount; i++) {
                glBegin(GL_QUADS);
                glVertex2i(0, 0);
                glVertex2i(16, 0);
                glVertex2i(16, 16);
                glVertex2i(0, 16);
                glEnd();
            }
            opengltime = (float) (System.nanoTime() - time) / 1000000000;
            System.out.print("OpenGL time: ");
            System.out.println(opengltime);

            Display.destroy();
        }
    }

}

Answer:

Rendering a single square is not very difficult. Essentially it boils down to windowing a piece of memory and filling it with a specific value.

Also the way you use OpenGL suffers from huge amounts of overhead. What you're measuring is not the efficiency of SWING vs. OpenGL, but the efficiency at making function calls. Ditch glBeginglEnd (they've been out of fashion for over 15 years now) and use vertex arrays. Also don't starve the GPU by spoon feeding it with drawing commands. Instead offer it an All-You-Can-Eat by means of vertex arrays of at least 100 primitives per drawing batch. Only then you're getting out of overhead-land.

Question:

In LWJGL 2, is there a way to set the display visibility? Similar to how you can call setVisible on a JFrame to show or hide the window. Basically what I want to do is create the OpenGL context using Display.create(), then show a loading splash screen while all my resources are loaded (requires context to be created) and then make the display visible.


Answer:

You could parent the display in a Canvas object you create, via Display.setParent. Then any changes to the parent's visibility will be reflected in the display object.

Otherwise couldn't you just make the splash screen in the context itself, and just switch what you're rendering when ready?

Question:

I've managed to get lwjgl working on a canvas inside swing, however when i open the application, the lwjgl opens briefly another window named 'Source'.

It is not really a problem since it all works afterwards, but it bothers me and i want to fix it.

I am not even sure of what's happening actually, here is a gif of what happens

The code on the gif is actually from another example where it works as intended

Here is the relevant opengl code, everything else on this project is swing component instancing

EventQueue.invokeLater(new Runnable()
    {
        public void run()
        {
            try {
                addLibraryPath("./lib/");
            } catch (Exception e1) {
                e1.printStackTrace();
            }
            try {
                Display.create();
                Display.setParent(canvas);
                GL11.glViewport(0, 0, 195, 195);
            } catch (LWJGLException e) {
                e.printStackTrace();
            }
            GL11.glClearColor(1f, 0f, 0f, 1f);
            GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
            Display.update();
        }
    });

Answer:

This is really embarrassing, since i found out what the problem as about 2 minutes after posting the question

I just had to swap

Display.create();
Display.setParent(canvas);

making it

Display.setParent(canvas);
Display.create();

I hope this somehow help someone

Question:

A friend asked me to develop a chart setup for a machine he is building. He has some very specific requirements about how the charts need to be displayed, and no existing api will satisfy those requirements. So I need to make a custom chart renderer, one option was to just take any java 2D canvas or to use OpenGL, which would be LWJGL. I used LWJGL 2 in the past, and i know it can be a canvas element, while LWJGL 3 can't. So the only solution I can have here is either have it broken up in frames like Gimp is, or have the gui as part of the LWJGL 3 frame. Those solutions are not appreciated for what needs to be done. Is there a way I could wrap the LWJGL 3 frame as a internal frame, or anything to make it stick to a java swing or java fx gui?

I use Java because I know it best, I don't have so much experiences in other languages.


Answer:

Look here is an interval chart:

I cant fit all the code on here unforunately, I will post it on github. But anything you can imagine can be done, I am not going to go through every way jfreechart can be customized but with some digging you can find the answers.

You can find the code on https://github.com/derrick3192/sliderchartdemo.git

If you want to add zoom buttons and what not I suggest you look at the:

plot.getDomainAxis().setRange

Or

plot.getRangeAxis().setRange

But I don't mean this offensivily but you can't come on stackoverflow with low rep (even though I don't have much rep) and claim all the charting libraries are not good enough, and you have to make your own, you will get downvoted for that so tread lightly.