But not well enough to understand why things are the way they are. KevinWorkman’s excellent link describes what you need to know in a fairly succinct and enlightening essay.
I’m not sure what you’re talking about here- the EDT is not an “OS event queue”. It’s a Java Thread that pumps events into Listeners. Nothing more, nothing less.
Lol, well I appreciate your direct answers, but how would you achieve those things? I’ve never heard of anyone doing it, because I presume that it’s impossible.
If it was possible, why does everyone choose to reinvent the wheel by making more GUI libraries rather than leveraging the existing Swing library? I know that swing uses java2d rather than opengl, but graphics2D can be over-ridden with calls to openGL so that can’t be the problem.
i’m not leaving swing if dont have to. edit (shakes fist at lwjgl 3.x) /edit
problem with paint-to-opengl is … AWT is calling paint form it’s thread.
we can call paint() from any thread and hope it does not explode, but when we’d try to create a look-and-feel implementation it would get us into trouble … or tons of code, dealing with proper queueing paint -> draw-calls in the correct thread.
The closest thing that I could google which showed swing components being re-used, possibly in a direct rendering game, was this project: https://code.google.com/p/swing-gl/
The problems I describe about the swing libraries being inflexible and not exposing hooks are made apparent in this statement by the swing-gl projects’ authors:
[quote]Important: At the moment we use a nasty hack to make event system work: Set dispatcher field of Container class with reflection. This hack most probably won’t work on non-SUN JVM’s and will break in the future. However we beleive event system can also be made work with a custom Toolkit and a dummy Peer. Indeed we seek help from AWT/Swing gurus about this subject.
[/quote]
I think this shows that the Sun programmers did not make the Swing library with re-usability in mind, they have designed the swing library to be used on the event dispatch thread only. Which is not a bad thing for most people and probably a sensible design choice. But it’s a pity for us game programmers who would like to use the swing components in a direct-rendered game, rendered in our own thread.
I could get into each of them individually if you wanted, but the point is that you can turn off Swing’s double-buffering and painting mechanisms and do your own active rendering on your own Thread.
However, if you think you have to be doing active threading in Swing, you either A) don’t actually have to or B) should be using something like libGDX that will handle it for you anyway.
Eh, that’s like saying: you can make any program by using machine language, so why does everyone choose to reinvent the wheel with other languages?
Swing is great for some stuff. It’s not so great for other stuff.
Again, I think you’re being pretty unfair, or at least measuring Swing against metrics that aren’t really compatible with it. It honestly seems like you might not really understand how threading works, or how the EDT is supposed to work. I agree that it can be pretty confusing at first, but I think it’s unfair to blame that on a lack of thought on the developers’ part.
I assure you that the developers of Swing put quite a bit of thought into their design decisions- probably more thought than any of us are putting into these forum posts.
Also keep in mind that a lot of the Swing developers went on to develop Android. They ain’t dummies.
If you really need that, you can absolutely do that. But you probably don’t actually need that.
I think this shows that the Sun programmers did not make the Swing library with re-usability in mind, they have designed the swing library to be used on the event dispatch thread only.
[/quote]
I was waiting to see what @KevenWorkman replied first, but there’s probably another hacky (but less hacky than above!) way of doing this, without going as far as creating a new Toolkit - run the main game loop on the (well, an*) EDT. The EventQueue will give you access to events which you can filter and dispatch as you like.
Stupidest threading decision in AWT / Swing is blocking threads and pushing a new EDT / EventQueue when a modal Dialog opens! : The above suggestion would break if a Dialog opened.
Which is still doing the work on the EDT - invokeAndWait() - the ideal way to make hard to find bugs - there’s a reason they left it out of JavaFX!
You can do active rendering in a relatively hack-less way by just disabling Swing’s painting and using your own thread. But you’re right, you’ll have to use the invokeLater() to move events from the EDT to your thread- but again, most people who think they need to do this, really don’t.
What would be the alternative? For the entire GUI to freeze up whenever a dialog was opened? Or for no modal dialogs to be supported?
[quote=“nsigma,post:27,topic:53555”]
JavaFX does have an EDT- they just call it the JavaFX Application Thread. And they do have an invokeLater() method, they just call it Platform.runLater()! But it’s interesting that they chose not to include a runAndWait() method.
You’re blurring together threads and modality. There’s no reason for dialogs not to be done using asynchronous callbacks - eg. the approach something like jQueryUI uses. Swing is mostly event driven, so it just seems weird to me that this isn’t the approach here.
That was what I was trying to say, possibly too cryptically! ;D
Modal dialogs do not cause a new Thread to spawn. They create a new Event Queue and Event pump, right on top of the current queue/pump. Think of it as recursion. A stack of queues and pumps, where only the top of the stack is active.
When you have an uncaught exception reaching an event pump callsite, however, a new EDT will be spawned, as the active EDT is considered in a state not worthy to recover.
the only thing that sun did not do well is to give us proper control over polling and flushing queues - which is done by the EDT for us.
would be nice to remove EDT all together and just (re)implement it’s purpose wherever we’d like … but then, if most people cannot use the EDT properly right now, how many will be able to write or use a custom implementation ?
good news if they dropped runAndWait() from javaFX. means they’re using their own framework properly. nothing stops your from implementing your own runAndWait() method, with a Lock and Condition
hmm … OK, that’s me misreading some ambiguous JavaDoc : - to me, that doesn’t count as “block the execution of the current thread”. Has that always been the case? Vague recollection of seeing new event threads spawned from dialogs in the long distant past, but guess that might be the other reason you mention.
Still doesn’t mean I like this (fake) blocking behaviour, but it’s a bit better than I assumed.
What exactly do you want by “proper control” above what EventQueue or a custom subclass gives you (assuming you can re-appropriate the dispatch thread)? Not that I don’t agree with all of your second sentence!
[quote]…processes (threads) and monitors (locks) are duals. Well, yes, it’s true. In some sense we are using the event thread to implement a global lock. We could invert things, and create a global lock that is equivalent to the event queue.
[/quote]
If there was more flexibility in the Swing API’s threading model then I think it would be a better library which could be used in directly-rendered games without forcing us to do everything on the EDT. The EDT is an unnecessary and annoying aspect of the API which could have easily been done differently, such as using locks or letting the developer use their own game loop thread. However, the Swing API has no flexibility to do this.
As I said, I can’t see why the Swing engineers couldn’t:
Expose a hook to let us see the OS event queue in our game loop thread if we want so we can take the events we want to consume and make game logic updates
Let us call an update method on the Swing components with any relevant events for them given as an argument which would happen in our game loop thread,
Let us call paint on the Swing components from our game loop thread and repeat.
@KevinWorkman and @PrinceC. While I appreciate both of your input on the forum since your posts are often very insightful and entertaining, in this case it’s disappointing to see you repeatedly dismiss me as ‘not really understanding how threading works’ while failing to answer my question, which is: show me how you can make Swing render in your own thread without the event dispatch thread (EDT).
If you can do it as easily as you say, I’d be very impressed. The code would be an important contribution to the community since the Swing library is well designed in general, we’re all familiar with the API and it comes included in the jdk.
I’ve tried to make Swing run in a direct rendering game not rendered on the EDT, and so have many others including the swing-gl programmers, but we all failed in one way or another. The swing-gl programmers only make it work using reflection hacks to overcome the lack of flexibility in the Swing API.
In my multiplayer networked game SydneyEngine (http://www.java-gaming.org/topics/multiplayer-top-down-view-shooter/18019/view.html), I use Swing menus but was forced to use invokeAndWait(renderSwingMenus) to draw the user interface on the EDT, since the swing API forces it to be so.
I agree with basil. I would like to use the swing GUI without having to change my threading model, which I think is completely unnecessary for a GUI to impose. Imagine if every library insisted that its code run on a specific thread. There’d be invokeAndWait equivalents every time I tried to use any libraries’ code, making quite a mess.
Dude, your whole response there continues to show me that you do not understand the problem you are trying to solve at all, and you really need to do some research (written by lots of other people) rather than insist we sit here and type lengthy multi-page treatises about it all.
But as a shortcut:
What you want to do with Swing is called Active Rendering. The nub of the gist is that you need to:
a) Paint in your main loop thread
b) Take any and all input events from the EDT and pass them in a thread safe manner to your main loop
or you could potentially just hop aboard the EDT and start running your game loop from there but I suspect trouble lies that way.
Your main issue is that Swing is designed as a passive event-loop driven system and it looks like you want to make a game which is almost always done in a totally different way. Games generally repaint the screen at a fixed rate or as fast as they can and do everything - direct input, logic, rendering - in a single thread “main loop”, occasionally doing clever stuff with other threads but that tends to be somewhat advanced. They’ve hacked a bit at Swing to make it possible but it’s not a smooth ride. If you want my advice, just stay away from Swing if you’re writing a realtime game of any sort.
All this stuff about blocking, multiple EDTs, event queues, OS hooks, etc - all red herrings, none of you need it or even need to know about it which is why it’s so well buried. Move along, nothing to see.
ja, that works. but how could it be possible to build a lookandfeel implementation drawing/interacting with a arbitrary game loop ? the more i think about it the more i look on the CGlib. i mean things are called from EDT (like paint() as a result of a OS event) which i cannot intercept without buttpain.
:o setting a proper BufferStrategy makes EDT not call paint() on a component and allows painting the whole component-tree in custom thread ?
i know how to use graphics2D speedy on a canvas - but this about GUI’s. how could we take swing and all it’s widgets and whatnots and use it with … libGDX or something ? i mean, without setting everything to setIgnoreRepaint(true) … or overwritting all paint methods … or writing a whole java.awt.Toolkit implementation.
just thinking, building a LnF is pretty simple, having it run a few GL draw-calls wouldn’t be too much to ask.
You can do all that already! To paint, you could use active rendering, or if you’re running your game loop in the EDT you could control the default Swing paint mechanism. For the other two, use Toolkit.getSystemEventQueue() to get access to the queue. If you’re running your game loop in the EDT, just pull events and dispatch (see component.dispatchEvent()). Otherwise, push your own EventQueue implementation on top of the existing and override EventQueue.dispatchEvent() to filter / pass to your game thread. The latter might have an issue if anything was using EventQueue.isDispatchThread() though.
Not exactly! Read the link @princec gave, in particular the second point under programming tips -
[quote]Use the setIgnoreRepaint method on your application window and components to turn off all paint events dispatched from the operating system completely, since these may be called during inappropriate times, or worse, end up calling paint, which can lead to race conditions between the AWT event thread and your rendering loop.
[/quote]
As I’ve already said, you don’t have to do everything on the EDT. The flexibility you’re complaining about not having? You have it.
Sorry, but I’ll take a single-threaded approach over dealing with locks and threads any day. The EDT approach is not just a Swing thing- like I already pointed out, most modern GUI libraries are single-threaded. Anything more than that is overkill for 99% of GUI applications. But if you really want that flexibility- you already have it.
You can.
You can.
You can.
I’m not trying to be condescending, but do you see how your attitude in this paragraph might suggest that you’re in a little over your head with this topic? A quick google of “Swing active rendering” would get you started. Have you done that? Have you posted any code that shows what you’re talking about? Nope. You’ve instead complained about things that aren’t true and have demanded that we post the code for you.
And here’s a really dumb program that follows the bullet points at the bottom of that link to perform active rendering in Swing, off the EDT:
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
* This is an example that shows the very basics of active rendering in Swing.
* Note that this code is dumb, does not use double-buffering (hence the flickering),
* and should not be used by anybody in a real program.
*
* If you think you have to do active rendering in Swing, you're probably wrong.
*
*/
public class Main {
public static void main(String... args) {
JFrame frame = new JFrame("Active Rendering Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JPanel myPanel = new JPanel();
//no more rendering on EDT
myPanel.setIgnoreRepaint(true);
//background will never be drawn by Swing, thanks to above line
myPanel.setBackground(Color.RED);
frame.add(myPanel);
frame.setSize(500, 500);
frame.setVisible(true);
Thread renderThread = new Thread(){
public void run(){
double ballX = 100;
double ballY = 100;
double speed = .1;
double deltaX = speed;
double deltaY = speed;
while(true){
if(ballX > myPanel.getWidth()){
deltaX = -speed;
}
if(ballX < 0){
deltaX = speed;
}
if(ballY > myPanel.getHeight()){
deltaY = -speed;
}
if(ballY < 0){
deltaY = speed;
}
ballX += deltaX;
ballY += deltaY;
Graphics g = myPanel.getGraphics();
g.setColor(Color.WHITE);
g.fillRect(0, 0, myPanel.getWidth(), myPanel.getHeight());
g.setColor(Color.BLACK);
g.drawRect((int)ballX, (int)ballY, 100, 100);
g.dispose();
}
}
};
renderThread.start();
}
}
Please see above. If you still have a question, please post your own code in the form of an MCVE.
Again, not trying to be condescending- but it sounds like you really need to overhaul your design. That’s why we’re saying you might not understand threading as well as you think you do, because you really seem to be misusing it.
Like I’ve said several times now, this is not just a Swing thing. Almost every GUI library (including OpenGL, Android, JavaFX, libGDX, and JMonkeyEngine) uses this model. I promise that the people behind these libraries have put more thought into it than you or I. The fact that you think this is ridiculous is why we’re suggesting that maybe you simply don’t understand the model. We aren’t trying to be condescending- we’re trying to help you understand.
Edit: And like Cas says, none of this really matters. If you really think you need to go through all of this rigmarole with active rendering and threading in Swing: you’re either wrong, or you should be using a different library that handles it for you.
Nuff of this. We all have our ill-informed moments. No need to ‘gang up’ on our beloved Keith. I’m sure lots of people found new information in this thread about the inner workings of Swing - we should focus on sharing such information instead of telling eachother how ill-informed we are, over and over and over. We don’t need N similar corrections from N people quoting the same statement. It gets old rather quickly.
I’m not saying this as a moderator - just as a slightly annoyed innocent bystander.