Meaningless Drivel is fun!*
The moose likes Swing / AWT / SWT and the fly likes In the background drawing thread, which is the better option? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Murach's Java Servlets and JSP this week in the Servlets forum!
JavaRanch » Java Forums » Java » Swing / AWT / SWT
Bookmark "In the background drawing thread, which is the better option?" Watch "In the background drawing thread, which is the better option?" New topic
Author

In the background drawing thread, which is the better option?

Seabook Chen
Greenhorn

Joined: Mar 30, 2011
Posts: 10
Hello All,

I am programming some games in Swing, everything is good. But in main Loop Drawing Thread. What option should I use?

Basically there are 2 options as far as I know:

1) Swing Timer class, which is easy to help you to setup the repeated thead. But the timer thread also put into the EDT to wait and get executed. Will this potentially block other gui's component, once I heavily draw the graphics and the GUI application get complicated.

2) Use Swingworker, I like the class, but in the definition, it's just for dealing with some heavy loading tasks, is it suitable for drawing all the graphics?

3) Or I may create a seperate thread, which is obviously not thread safe for the application.

Anyway, what's best practise for doing this?

Thanks very much indeed.
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3575
    
  14

What you can do is have a BufferedImage field in your class, and when paintComponent() is called, you just draw this image. This should be a fast operation, and your GUI should remain responsive.

In a separate thread (you can use a SwingWorker or a regular thread, it doesn't matter much), you can update the BufferedImage whenever necessary, and then call the repaint() method. Just make sure access to the BufferedImage is mutually exclusive, by synchronizing on it.
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19649
    
  18

You don't need to synchronize with SwingWorker, as long as you do any updates to it on the EDT. So in simplified form:
As long as each update gets its own SwingWorker there are no synchronization issues:
- the SwingWorker's image is accessed from two threads (the SwingWorker thread in doInBackground() and the EDT in done()) but done() is guaranteed to run after doInBackground() has finished.
- the ImagePanel's image is accessed from the EDT only.


SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6
How To Ask Questions How To Answer Questions
Seabook Chen
Greenhorn

Joined: Mar 30, 2011
Posts: 10
Thanks for the response guys. I've tries to ask in the IBM java forum, there are no response and IBM forum seems quiet and boring.

So, you guys mean use SwingWorker instead of Swing Timer. Awesome, I will change the code.

Thanks,
Seabook
Seabook Chen
Greenhorn

Joined: Mar 30, 2011
Posts: 10
Rob Spoor wrote:You don't need to synchronize with SwingWorker, as long as you do any updates to it on the EDT. So in simplified form:
As long as each update gets its own SwingWorker there are no synchronization issues:
- the SwingWorker's image is accessed from two threads (the SwingWorker thread in doInBackground() and the EDT in done()) but done() is guaranteed to run after doInBackground() has finished.
- the ImagePanel's image is accessed from the EDT only.



But one thing you guys maybe misunderstood is, it's an infinite drawing loop to draw all the gaming backgrounds or updated status image, instead of just load a bunch of images at the very beginning. After all, it's a game, you have to repaint all the stuff time by time.










Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3575
    
  14

Well, I guess you can just continuously draw your game scene to a new BufferedImage in your main loop, and when it's done, you pass it to your panel, which then assigns it to a volatile BufferedImage field. Since it is a simple atomic operation, you don't have to worry about synchronization; as long as you don't make changes to the object after you've passed it to the panel.
Seabook Chen
Greenhorn

Joined: Mar 30, 2011
Posts: 10
Thanks for all the reply.

I just found an awesome Swing Gaming website. I wanna share with you guys, which can help you easily understand how to use swing to build some games.

http://zetcode.com/tutorials/javagamestutorial/

Enjoy reading and happy coding.

Thanks,
Seabook
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19649
    
  18

Version two:
This time there is even less worry about synchronization; the SwingWorker's BufferedImage is a local variable now, and process(...) is executed on the EDT just like done().
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3575
    
  14

Hey Rob, after process() gets called, does the EDT clear the list of chunks again?

I'm not very familiar with SwingWorker, because it's a 1.6 feature, and my crummy old laptop runs 1.5.
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19649
    
  18

publish puts everything into some internal storage. Then once in a while everything that was published is sent as a List to the process method, and the internal storage is emptied. So once an element is sent to process it's gone from the internal storage.

I first fell into the biggest publish-process trap - I assumed that since I published only one element at a time, I would get a List of size 1 each time. Boy was I wrong. But you know what they say about assumptions - it's the mother of all screw-ups.
Seabook Chen
Greenhorn

Joined: Mar 30, 2011
Posts: 10
Stephan van Hulst wrote:Hey Rob, after process() gets called, does the EDT clear the list of chunks again?

I'm not very familiar with SwingWorker, because it's a 1.6 feature, and my crummy old laptop runs 1.5.


2 main things SwingWorker can do.

1) return the final result, and load some heavy resource.
2) update intermit state, which is very helpful. You could make a progress bar based on that.

Another important thing is, SwingWorker will not block EDT, it's in another thread.

Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19649
    
  18

Well, the doInBackground method at least. done and process are still executed on the EDT.
Seabook Chen
Greenhorn

Joined: Mar 30, 2011
Posts: 10
Rob Spoor wrote:Well, the doInBackground method at least. done and process are still executed on the EDT.


Current thread: The execute() method is called on this thread. It schedules SwingWorker for the execution on a worker thread and returns immediately. One can wait for the SwingWorker to complete using the get methods.

Worker thread: The doInBackground() method is called on this thread. This is where all background activities should happen. To notify PropertyChangeListeners about bound properties changes use the firePropertyChange and getPropertyChangeSupport() methods. By default there are two bound properties available: state and progress.

Event Dispatch Thread: All Swing related activities occur on this thread. SwingWorker invokes the process and done() methods and notifies any PropertyChangeListeners on this thread.

doInBackgound is a seperate thread to dealing with heavy task, which is designed for not blocking the EDT, otherwise you won't have a response and interactive UI.

Thanks,
Seabook
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3575
    
  14

Oh, I almost forgot. Thanks Rob!
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19649
    
  18

You're welcome
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: In the background drawing thread, which is the better option?
 
Similar Threads
MouseEvent too slow or am I missing something?
Canvas HELP!!!
Painting dissappears during resizing (with mouse)
hi please help with conversion from awt to swing
repaint entire component