I just gave up on the roll-my-own GUI and converted to Swing - its what I know and its beautiful. I use direct rendering in my game loop thread and while I know that painting Swing/AWT components directly from such a thread is not safe, I read in a book somewhere that you can stop the AWT Event dispatching thread from painting by installing a 'NullRepaintManager', a class you make as a sub-class of RepaintManager that over-rides:

Apparently that stops 'OS-level' paint requests but I'm not sure if it stops internal painting on the AWT Event thread. I did this to stop the AWT Event dispactching thread from painting so I can call aSwingComponent.paint(myGraphics) from my game thread without threading problems. It seemed to work fine at first, but sometimes my game freezes and I fear that its because there is a thread conflict. I assume its because things like JTextFields paint themselves (like the flashing caret) on some thread (the Event Dispatching thread?) which conflicts with the painting of that JTextField in my game loop thread.

How can I stop painting in the Event Dispatching thread for good or am I barking up the wrong tree?

"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."

You can also use the invokeAndWait (or invokeLater) method of javax.swing.SwingUtilities, that will allow you execute code in the Event Dispatch Thread. If you execute all the game code there eventually then it's much easier to have normal swing components as game controls, because you won't have to queue and synchronize everything.

That article in the java tutorial is a relief because all other Sun documentation says that Swing components can't be painted from any thread except the Event Dispatch thread....

All the other articles youve read assume you are using Swing/AWT. If you were then yes, yo uwoudl have yo paint from the EVent thread because Swing is not thread safe.

In this case you are totally by passing those mechanisms and turnign off Swing/AWT rendering entirely so its safe to paint from antoher thread. You still shoudl only paint from one thread though. (in active rendered apps this is generally your own game thread.)

Got a question about Java and game programming? Just new to the Java Game Development Community? Try my FAQ. Its likely you'll learn something!

Although the AWT event thread can't paint the Swing components because I turned that off, it can still modify the state of the components at the same time I paint them from my game thread.

For example, what if I paint a JButton from my game thread while its state is being changed in the AWT Event thread when the button is rolled over whith the mouse (or the JTextField is typed into, etc). So how can I possibly paint Swing components from my own thread??? I fear this is why my game freezes when I play around with the Swing menus I added.

Painting does not modify model state so its perfectly safe as long as you dont re-enter the paint code.

Great, I wasn't aware of that. I wonder how that works because if I type delete (runs in AWT Event Thread) in a JTextField and remove a character mid-way through my game thread's paint, you'd think that there'd be an ArrayOutOfBoundsException or the like thrown when the game thread tries to paint the character that no longer exists.

This hasn't happened though, when I hold down delete in the JTextField after a short time my game thread just freezes and stops painting anything.... Anyhow, I'll make sure its not because I'm re-entering the paint code accidentally.

"Initially there was a rule that it is safe to create and use Swing components until they are realizedbut this rule is not valid any more, and now it is recommended to interact with Swing from EDT only"

For my Swing menus I have only had deadlocks a couple of times, but the JTextFields I use reliably cause AWT Event thread deadlocks when I type or delete characters. What kind of Swing components are you using in your game? Maybe it only works because you use simple components which rarely cause a dead-lock with your game thread.

I'd love to hear other developer's experiences, surely not everyone has created their own self-rolled GUI. I assumed Swing was the default for game developers...

For my Swing menus I have only had deadlocks a couple of times, but the JTextFields I use reliably cause AWT Event thread deadlocks when I type or delete characters. What kind of Swing components are you using in your game? Maybe it only works because you use simple components which rarely cause a dead-lock with your game thread.

I think I'm using virtually every Swing component known somewhere or other! Not everything works quite as expected (JOptionPane is a big no-no) but mostly it does. All my painting etc is done ultimately under the JOGL display () method which I suspect is in fact on the EDT.

If pressing a button or doing anything with the mouse - which all happens from the EDT *UNLESS* lots of work is done to requeue all the stuff to the game thread in every mouse listener and... jeez I'm dizzy now - affects the game state, and if on the other hand the game state might affect the model of a swing component (say, a thing dies and is removed from a list) then we have two threads accessing the model of a swing component.

I am surprised that this isn't a common problem, which is why I made a thread (org.javagaming.Thread, not java.lang.Thread ) about it a while ago, and it basically seemed that no one uses swing components for their games. I for one don't want to write my own version of JTree so I use the approach mentioned by me above (SwingUtils.invokeAndWait to ensure logic update and active rendering from the EDT). Really, it's the only solution I can imagine!

I use Swing Components in direct-rendering games as well. In fact, I set up one Component for the whole screen that everything gets drawn to. I use regular Components as well. Dialogs are the only things that don't seem to work.

I also have a NullRepaintManager and used setIgnoreRepaint to true. Here's my code that actually draws the Components to the screen:

//draw Swing components//wrap the drawing in an EventQueue if and only if this method isn't already in an//the AWT event thread. Swing Components must be drawn in the AWT event thread, but//invokeAndWait can't be called from within the AWT event thread.finalJLayeredPanelayeredPane = mainFrame.getLayeredPane();try {//if this is in the AWT event thread, just paint the componentsif(EventQueue.isDispatchThread())layeredPane.paintComponents(g2);else { //else this isn't in the AWT event thread, so invokeAndWaitEventQueue.invokeAndWait(newRunnable() {publicvoidrun() {layeredPane.paintComponents(g2);} }); } //end else this isn't in the AWT event thread } catch(Exceptionexception) {ErrorLog.output(exception,ErrorList.applicationGameFrameErrorPaintingComponents); }

I doubt the code will help you because you're already doing the same thing. But I posted it anyways. It was originally inspired by similar code from a book called "Developing Games in Java". My code's "better" than the code in the book, but it's the same general idea.

I tried to make a test case that produced the same problem but it's working fine >> not deadlocking which I couldn't understand. But now I realize that in my game the JTextField is in a movable JInternalFrame whilst in the test case it isn't. Perhaps I'm having the same trouble as fletchergames since JInternalFrames are probably similar to Dialogs- "Dialogs are the only things that don't seem to work".

How are you using them? Id like to see the code as Im having trouble even iomaging a multi-trheaded access case to the model..

I'll post the test case when I get home and have tried it with the JInternalFrame. Basically I create a frame and put compnents in it and just continuously paint them in the main thread. I manipulate the components with the mouse & keyboard (and this happens in the EDT which must sometimes conflict with the main thread, but doesn't for my current test case....)

It was originally inspired by similar code from a book called "Developing Games in Java".

Yes! By David Brackeen, that's the book where I got the code from. Thanks for posting your code.

The interesting thing about what you do is that you paint your Swing components in the EDT (through invokeAndWait) onto the BufferStrategy and then you show the BufferStrategy in your own thread. So you're kind of using a weird combination of passive and active rendering. This should have the same draw back pointed out by Jeff earlier that (part of) the painting is done in the EDT - so your screen paints may come late while you wait for the EDT to do the job - not really direct/active rendering.

Since all of you - Dave, fletchergames and Ask_Hjorth_Larsen seem to only be having success with painting from the EDT then perhaps Swing cannot be used for non-JOGL direct-rendering games.

"The single-thread rule (from the Java Tutorial)Once a Swing component has been realized, all code that might affect or depend on the state of that component should be executed in the event-dispatching thread....Realized means that the component's paint() method has been or might be called. A Swing component that's a top-level window is realized by having one of these methods invoked on it: setVisible(true), show(), or (this might surprise you) pack()."

Since painting depends on the state of the component then painting from outside the Event Dispatch Thread (EDT) must not be thread-safe. Is this reasoning correct because it makes Swing useless for active-rendering and also contradicts what Jeff said in an earlier post.

"The single-thread rule (from the Java Tutorial)Once a Swing component has been realized, all code that might affect or depend on the state of that component should be executed in the event-dispatching thread....Realized means that the component's paint() method has been or might be called.

No.

In that context it means it has been ro might be called BY THE AWT PAINT tHREAD.

The problem with all these things you keep quoting is that they are ALL written with the asusmption that you are doing normal AWT/Swing repainting, *not* active rendering.

I'm not saying your wrong, because I don't know those internals, but I think its more likely you are then you arent. I DO knwo that all these articles are orthogonal to the issue.

This is because the ONLY source on this option and what it really does under the hood is Mike Martak, who is no longer with us and thus cannot comment. Given that, I take his writings, which DO address manual painting, as definitive.

Question: have you gotten rid of all the WEIRD sh-t you were doing?

Quote

I read in a book somewhere that you can stop the AWT Event dispatching thread from painting by installing a 'NullRepaintManager', a class you make as a sub-class of RepaintManager that over-rides:

setIgnoreRepaint(true); // disable OS-triggered repaint requests RepaintManager.currentManager(this).setDoubleBufferingEnabled(false); // disable double-buffering since we do this in the BufferStrategy

content = new JPanel(new BorderLayout()); setContentPane(content);

textField = new JTextField("Type & delete stuff here", 50);

JPanel panel = new JPanel(new BorderLayout()); panel.add(textField); content.add(panel); //content.add(textField); // comment out the above 3 lines and // uncomment this and it will work - // there will be no deadlock

I've found that component.paintComponent(Graphics) works when its children have no child components themselves. When its child components have their own child components then deadlock results. You can see this by commenting out the intermediate JPanel that sits between the content pane and the JTextField.

I've read a lot about how GUIs work, including the SWT (IBM's alternative to AWT/Swing) and as far as I can see (not very), Swing is fundamentally flawed for use in direct-rendering games since it is so closely tied to the AWT Event Dispatch Thread (EDT). As Ask_Hjorth_Larsen said it looks like the only thread-safe way Swing can be used is to have the whole game running in the EDT which won't work.

The SWT (Standard Widget Toolkit) would work in direct-rendering games since there is no EDT, all communication with the Operating System for events and painting is done through the main thread. But I've decided not to use the SWT because its not completely flexible & portable due to the way SWT components are all backed by their native/heavyweight OS equivalents.

I've decided to go with my own crappy GUI system because at least it works and I know what it's doing.

I'd love to know if anybody has used Swing successfully without doing EventQueue.invokeAndWait() etc, but unless I've stuffed up something obvious, the above example shows how Swing can't be used in a direct-rendering game.

I think the problem is that the AWT event thread is accessing your swing components at the same time that you are drawing them from another thread. I have had the same problem and the following solution worked for me.

/** * This event queue is synchronized on the MUTEX. This lets one control when * events can be dispatched. * * Note, changed to be a singleton to get it working on pre 1.4.2 VMs. * * @author Luke * */finalpublicclassSynchronizedEventQueueextendsEventQueue {publicstaticfinalObjectMUTEX = newObject();

100% Sensational! Luke you are a legend, that peice of code is a silver bullet!

Not only is it kicking ass in the test case but I just tried it in my game and it works perfect!

I thought that the synchronized block would sap performance but no, the frame rate doesn't change whether or not I use the SynchronizedEventQueue. That's a very elegant solution.Being able to use Swing in my menus will make life a lot easier .

By the way, what is the cost (if any) of sync'ing these events? Speed? Mouse & keyboard responsiveness? In the test case how much of the game loop needs to be synchronized? To reduce cost of sync'ing, could you safely change it to this since much time is taken blitting from the bufferStrategy to the screen compared with painting to the bufferStrategy:

I think the problem is that the AWT event thread is accessing your swing components at the same time that you are drawing them from another thread. I have had the same problem and the following solution worked for me.

...

Wow, I never thought of trying anything like that before. When I get a chance, I'll try doing something similar in my code to see what happens. Thanks for the idea.

It's possible to use active rendering within the EDT unless I have completely misunderstood the concept. Rendering is not magically active or passive as determined by which thread it runs from. The repaint() system, which queues and collapses calls and so on is passive rendering. If you perform the rendering immediately when desired, as opposed to queueing and collapsing, then it is active rendering. If this is correct (which is not trivial because the invokeAndWait method which I'm going to suggest may involve some EDT queueing along with peripheral input and so on, though no repaint management takes place), then the invokeAndWait method can easily be used to render actively from the EDT. I assume the invokeAndWait is sufficiently efficient (i.e. that the passive rendering overhead which we hate is incurred mostly by the paint management and thus not the queueing itself).

Jeff said:

Quote

Right. hats one thread.

Where is the other one?

Its that which im having a hard time imgining.

It's the main Thread of the game, which is used for the main loop. That's not the EDT, so it *is* another Thread.

So basically the user fiddles with the mouse and the corresponding stuff happens in some actionPerformed or mouseMoved method from the EDT. Perhaps the user action causes the window to scroll. Now, it's a pain in the lower back to queue this event and execute it from the main thread instead of the EDT. So if it's executed from the EDT then the window scrolls while the main thread is likely busy painting, possibly resulting in tearing because - well - perspective changes while the screen is updated.

the difference between passive and active is that passive is wenn it's told to/wenn it's needed vs active which is all the time.

the whole deathlock issue has to do with swing not beeing thread save. and has inheritely nothing todo with the whole active of passive rendering. It's the way we achive active rendering that causes the issues.

I tried Luke's code. Since I was using active rendering before (yes, from within the EDT), that wasn't really the issue. I was hoping for a performance gain. It turns out that frame rate is, on average, the same.

It may end my problem with dialogs being displayed oddly, but I'm not really concerned with that as I wrote my own almost-a-dialog class almost a year ago.

I also tried removing the NullRepaintManager code (which came from Developing Games in Java). There was no performance gain, but I was getting periodic NullExceptions for some reason. I was already randomly getting NullExceptions at start up once I started using Java 6 beta. But the NullExceptions were caught and had no effect except to add text to the error log. Since I then suspected that the problem was somehow solved by NullRepaintManager, I moved the NullRepaintManager to occur earlier in the code. Now there are no more NullExceptions at all.

I think the issue is that the regular Java RepaintManager was trying to draw Components that weren't completely initialized after I went into full-screen exclusive mode but before I installed the NullRepaintManager. I could probably do away with the NullRepaintManager altogether if I made sure that Components weren't made visible before their time, but it's easier just to keep the NullRepaintManager.

I was reading your postings since I wanted to use Swing as data input framework for my game so that I don't need to develop one of my own.

Here I send you a little test program which open a dialog for text input and it seems to work OK. Don't know if it represent the kind of problems you have with your rendering code.

I followed the active rendering examples from the book Killer Game Programming it seems to be deadlock free (can't assure it though).

The problem I found with this is that it seems to me that the code is somewhat slow and the cube doesn't get rendered solid but I shows some flickering. So I post the code to see if anyone has a better idea of why those things are happening.

The problem I found with this is that it seems to me that the code is somewhat slow and the cube doesn't get rendered solid but I shows some flickering. So I post the code to see if anyone has a better idea of why those things are happening.

...

Try using the BufferStrategy class instead of drawing to your own BufferedImage and then drawing that to the screen. BufferStrategy can use page flipping if your graphics hardware supports it. And, if if it doesn't support page flipping, I believe it can wait for the vertical retrace period (or whatever it's called) to avoid drawing to the video memory while it's being displayed to the monitor.

If you don't want to do use BufferStrategy for some reason, at least try accelerating the BufferedImage using Image.setAccelerationPriority. That's a bad idea though because Image.setAccelerationPriority just suggests that image acceleration occurs. So, you should really use BufferStrategy.

Its a memory leak bug which would pop up as an OutOfMemoryError when the GraphicsConfiguration is changed. It popped up for me when I tried changing to full screen mode and back in the middle of the game. Its fixed in Mustang (Java 1.6).

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org