simple interface within an opengl application

hi guys, first time here ;]

i’ve been learning opengl for a while now and decided to create a simple application to test my skills, i’m creating a simple model viewer that loads an external .obj file, this viewer should support different kinds of texture mapping, lights and so on

to accomplish that i need some kind of a simple interface that lets me load my files and change some settings, like position, colors, etc, it would also be nice to have some mouse and keyboard for easy access too

i’m all fine with opengl but i’m a complete noob with java interface, not only i don’t know much of how to implement a simple interface i also don’t know how that interface can communicate with the rendering process

could anyone point me out to simple interface and maybe some examples on how accomplish that within an opengl application? my searches haven’t been very fortunate, i only find examples and libraries for custom made interfaces, but i need something more streamlined

remember, i only need some textareas, checkboxes, dropdown lists, browser fields and so on…

thx in advance :]

If you’re using LWJGL, check out TWL, I hear it’s good.

You could also combine AWTGLCanvas with standard swing/awt gui elements, but there are issues when they need to render overtop of it.

If you’re using JOGL, never mind TWL, but iirc it integrates with swing/awt nicer than LWJGL, so that would be the direction to look in.

For basic keyboard and mouse access, take a look at org.lwjgl.input.Keyboard and org.lwjgl.input.Mouse
For a simple-ish self-contained example using those, take a look at this code.

[quote]i’m all fine with opengl but i’m a complete noob with java interface, not only i don’t know much of how to implement a simple interface i also don’t know how that interface can communicate with the rendering process
[/quote]
Generally, the UI code will have a callback that gets called when an action occurs (such as the user pressing a button or the like) and in that callback, you’ll do whatever you need to do to respond to it. If you’re going to use swing or awt, the callback will be on a different thread so you’ll need to be careful to do things in a threadsafe manner. I suggest looking up some swing tutorials for quick examples.

sorry for not specifying, i’m using jogl

about the different threads, does that means i have to create some sort of flags that i need to check in order to communicate between the two? isn’t there any “nicer” way?

I’ve used FengGUI for that kind of UI in JOGL. It’s a bit buggy, but certainly usable.

The previous poster’s comment about threading wasn’t sufficiently clear. The thread in which your public static void main(String[]) method gets executed isn’t the thread in which the UI events are raised, but typically all the main method does is this:

public static void main(String[] args) {
    SwingUtilities.invokeLater(new UIBuilder);
}

where UIBuilder implements Runnable and builds the UI. Then you only have to worry about threading if the operations you do in response to UI events are too slow to go in the same thread as the UI handling per se.

Yep, on both counts. :slight_smile:

Is there a reason to do that? AFAIK it’s perfectly OK to build the UI on the main thread. It’s only after you pack() / show() the main window that you have to limit access to the UI to the event-dispatching thread only.

What I meant was that the callbacks will be on a different thread than your GL rendering. So you’d have to be careful about making GL calls in the callbacks (either GLContext.makeCurrent() the event thread, or just tell the rendering thread what to do).

TWL can also be used with JOGL. You just have to write (or port) a Renderer implementation.
TWL’s rendering & input subsystem is completely abstracted. The provided renderer for LWJGL is a simple GL11 based renderer. With libgdx you can run TWL also on Android. If you want you could even render it using AWT :DD

Why not using my JOGL port of Nifty GUI? It works really fine and it is actively (daily) maintained ;D

Sounds cool… but I’m afraid that a quick google for ‘Nifty GUI jogl’ didn’t give the healthiest looking set of results… it sounds like you consider it stable enough to use; I might have a play sometime if you post a link.

As for making swing components on the main thread; most of the time it doesn’t matter, but officially it’s not proper (potential deadlocks). I was playing around with Substance LAF recently, and found they are deliberately strict about this… see http://stackoverflow.com/questions/491323/is-it-safe-to-construct-swing-awt-widgets-not-on-the-event-dispatch-thread (not my question) and related blog posts etc. So that’s a concrete example where it causes a real problem.

While it is difficult to find explicit Sun/Oracle documentation online that says so, it is indeed the “new” recommendation to even create your GUI on the EDT. It is very rare, but not unheard of, to experience therading issues (layout issues, etc.) when not doing so. There are some good threads about this in the Swing forum on forums.oracle.com.

I know this argument is unconvincing since I have no definitive source to cite :persecutioncomplex:, but one thing to consider is that all of the Swing examples in the official Swing tutorial now have a main method like this:


public static void main(String[] args) {
    //Schedule a job for the event-dispatching thread:
    //creating and showing this application's GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            createAndShowGUI();
        }
    });
}

This smells like bullshit cargo-cult programming to me. Swing has never required this in the past, and until there’s a swing component visible I don’t see why it would make any difference. Are you saying that they’ve broken backwards compatibility and all of the existing code that doesn’t wrap it up in invokeLater() is now broken?

The Java tutorial is pretty explicit that

[quote]An initial thread schedules the GUI creation task by invoking javax.swing.SwingUtilities.invokeLater or javax.swing.SwingUtilities.invokeAndWait.
[/quote]
http://download.oracle.com/javase/tutorial/uiswing/concurrency/initial.html

[quote]Some Swing component methods are labelled “thread safe” in the API specification; these can be safely invoked from any thread. All other Swing component methods must be invoked from the event dispatch thread. Programs that ignore this rule may function correctly most of the time, but are subject to unpredictable errors that are difficult to reproduce.
[/quote]
This is also what I was told by my tutor at college (fwiw)… It always seemed pretty pointless (as long, as you say, no component has actually been realised), and the only time it caused a problem for me was using Substance, where the devs have taken it upon themselves to enforce strict EDT usage since they clearly encounter a lot of bug reports from people who write incorrect swing code and get away with it, sometimes indefinitely. http://www.pushing-pixels.org/2008/07/15/stricter-checks-on-edt-violations-in-substance.html (that was what I wanted to link to before; had I known my post would be totally ignored I might have made more effort to dig it out).

I don’t have a source that clearly shows whether this has always been the case, but clearly it comes as no surprise for someone responsible for maintaining a library like Substance that, yes, there is some theoretically incorrect legacy code out there that is liable to fall over at some point. Whether my own code would ever have fallen over had I not been told off by Substance, we’ll never know, because now I have ‘carbon culted’ those extra ~3 lines of code into my program…

There’s only a rather subtle distinction between the kind of code that ‘works’, and something like http://weblogs.java.net/blog/alexfromsun/archive/2005/11/debugging_swing_1.html

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

public class BadCode {
    public static void main(String args[]) {
        createGui();
    }

    private static void createGui() {

        //this code must be run on EventDispatch thread!

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(new GridBagLayout());
        JEditorPane pane = new JEditorPane();
        pane.setText("Edt matters!");
        pane.setSelectionEnd(pane.getText().length());         
        frame.getContentPane().add(pane);        
        frame.setSize(new Dimension(200, 100));
        frame.setVisible(true);
        
        //clear selection
        pane.setSelectionStart(0);
        pane.setSelectionEnd(0);
    }
}

which is wrong.

Take a look at this.

Relevant excerpt:


An application's GUI can often be constructed and shown in the main thread: The
following typical code is safe, as long as no components (Swing or otherwise)
have been realized:
public class MyApplication {
public static void main(String[] args) {
   JFrame f = new JFrame("Labels");
   // Add components to 
   // the frame here... 
   f.pack(); 
   f.show(); 
   // Don't do any more GUI work here... 
   } 
}

So I’d say if this is no longer true, they definitely broke backwards compatibility. My guess is though, it’s enough of a pain to explain that they just decided it’s simpler to say “do everything on the event dispatch thread” even though that’s not actually required.

[quote=“avm1979,post:12,topic:36073”]
That sounds reasonable. Of course, there is something to be said for clear simple rules, not just so that they’re easy to explain - although it feels pretty fishy when the only discernible effect is to add boilerplate.

“This article about multithreading in Swing was archived in April 1998.”

So? Code written against it is still valid and still exists in the wild. Which means it’s either still ok and the invokeLater() is unnessesary boilerplate, or they’ve made a (reasonably large) compatibility breaking change.

I suspect that they were just fed up of the tons of bad programmers who just copy/paste from the tutorial code without realising that they need to do stuff on the EDT, so to save themselves some headaches they’ll just make those people copy/paste the invokeLater() stuff as well.

[quote=“Orangy Tang,post:15,topic:36073”]
You must be kidding right? They definitely broke backwards compatibility. They do it all the time.

Well it’s definitely in the docs for Java 6 - http://download.oracle.com/javase/6/docs/api/javax/swing/package-summary.html

However, I wouldn’t call it a compatibility breakage, as it was always broken - the old advice was wrong. I guess with greater use of multicore machines, bugs may have become more frequently visible, but they were probably always there.

Yeah it’s weird, here’s an interesting blog post about it by Kiril G of Substance fame:

http://www.pushing-pixels.org/2008/07/15/stricter-checks-on-edt-violations-in-substance.html

His look and feel API actively breaks apps that run swing code outside the EDT! Pretty crazy

From Horstmann’s “Core Java” vol. 1, Chapter 14 Multithreading/Threads and Swing:

Seemed like it might be worth quoting this pretty much as a whole. Five minutes of typing. Big deal.

Horstmann discusses the single-thread rule: “Do not touch Swing components in any thread other than the event dispatch thread.” Then, mentions that there are a few exceptions to this rule. For example, there are a number of Swing methods that are thread safe, and are marked so in the API with the sentence “This method is thread safe, although most Swing methods are not.”

He writes that originally, "any thread was allowed to construct components, set their properties, and add them into containers, as long as none of the components had been REALIZED. A component is realized if it can receive paint or validation events. This is the case as soon as the setVisible(true) or pack(!) methods have been invoked on the component, or if the component has been added to a container that has been realized.

"That version of the single-thread rule was convenient. It allowed you to create the GUI in the main method and then call setVisible(true) on the top-level frame of the application. There was no bothersome scheduling of a Runnable on the event dispatch thread.

"Unfortunately, some component implementors did not pay attention to the subtleties of the original single-thread rule. They launched activities on the event dispatch thread without ever bothering to check whether the component was realized. For example, if you call setSelectionStart or setSelectionEnd on a JTextComponent, a caret movement is scheduled in the event dispatch thread, even if the component is not visible.

"It might well have been possible to detect and fix these problems, but the Swing designers took the easy way out. They decreed that it is never safe to access components from any thread other than the event dispatch thread. Therefore, you need to construct the user interface in the event dispatch thread, using the call to EventQueue.invokeLater that you have seen in all our sample programs.

“Of course, there are plenty of programs that are not so careful and live by the old version of the single-thread rule, initializing the user interface on the main thread. Those programs incur the slight risk that some of the user interface initialization causes actions on the event dispatch thread that conflict with actions on the main thread…”

Any typos in the above, and the simplified formatting is due to my typing.

Thanks for typing that up. :slight_smile: So it was ok, but was too easy to mess up, people messed it up, and at some point was made officially wrong.