views:

5428

answers:

4

I have a Java Applet that uses AWT. In some (rare) circumstances, the platform does not refresh the screen properly. I can move or minimize/maximize the window and see that my applet refreshed properly. I am looking for code that will give me the fullest possible applet screen repaint, simulating the behaviour of a minimize/maximize.

I've tried calling various combinations of paint()/repaint()/invalidate()/update() on the parent containers and recursing on various children. However, no combination (that I've found) cleans up the framework bugs that I am encountering. I am looking for techniques to fully refresh the applet, even if they may cause some slight flickering, as I will be invoking this code only on the problematic platform.

In my tests, moving to Swing did not help resolve my problem.

By the way, this is a simplification of my previous (more complicated) post: http://stackoverflow.com/questions/184491/java-applet-awt-refresh-problem-mac-os-x-104

Edit: Investigation in threading did not solve this problem. Marking best answer as the good one.

+1  A: 

The method to use for this kind of problem is repaint, as you've mentioned. It's possible you are seeing an issue with the JVM you are using. I'd recommend using different versions of the Sun JVM and even the MS VM for IE to see if this is a VM related problem - it may actually be unrelated to your code.

I haven't actually tried this before, but a creative way (ie. nasty hack) around this might be to execute javascript from the applet to call a DOM method to do a mock resize of the window or perhaps call focus on the body in an attempt to cause an external re-drawing of the canvas.

J c
- This is a problem with Java on Mac OS X 10.4, regardless of the version of Java (1.4 or 1.5 or other). - I can't use JavaScript as I'm running inside Java Web Start. - How would you repaint? The top level container only or all children in a depth-first search?- Would you invalidate first?
Jason Kealey
Normally I would expect repaint on the top level container to be sufficient. However, this sounds like it may be a timing issue related to threading (unfortunately), as suggested by Bill K.
J c
+2  A: 

This happens all the time if you are not programming carefully in AWT/Swing.

First of all, you should do ALL work on the event thread. This means you can't do any of it in your main statement (or anything it calls directly). I know every Java GUI app ever invented violates this rule, but that's the rule.

For the most part, they used to say you could use a non-awt thread until the window was "Realized" (pack/setVisible), but Sun figured out that didn't always work.

Second, when you get an event on the AWT thread, be sure to return it quickly. Never sleep or execute a long operation.

Third, (and this is an extension of "First", if you get a callback that is NOT already on the AWT worker thread, be sure to put it on the AWT thread before doing anything with the GUI.

Generally, any event generated by an AWT component will be on the correct thread. Events generated by timers, manually created threads, or the one handed to main() are not.

Bill K
I will investigate the various threads used in this scenario. Have you heard of any threading issues that occur more often on Mac OS X 10.4?
Jason Kealey
They certainly could since the threading issues would be highly dependent on how the redraw is done and timing in general. I have had problems like this where I had to start over with something very simple and add-on/test one step at a time.
Bill K
Should you be calling JDialog.setVisible(true) on the event thread? It seems that it would block the event thread until the dialog closes?
Roy Tang
A: 

I was able to fix 99% of my AWT Applet redraw issues by switching to Swing. Swing seems to be more reliable on refreshing.

Earlier I had a lot of manual repaints() in my applet code, but with Swing these were removed and applet is now faster especially under Terminal Server / LTSP.

I placed critical stuff inside this:

public class VeryFastPanel extends JPanel {



    /**
         *
         */
        private static final long serialVersionUID = 1L;

        public void update(Graphics g) {

      paint(g);
    }

}
Tom
+1  A: 

Not sure if this is related to what you've seen, but if you get up against the performance of the AWT Event Queue the java 2d + 3d world (graphics pipeline folks) will point into a threaded strategy and then you'll get into the dispose problem.

This discussion has been looking at designs employing the AWT Event Queue for graphics, as in using "repaint".

In the threaded approach, there is a shutdown problem.

Notes in java/awt/SequencedEvent for "dispose" point us to "AWT Threading Issues" and "Autoshutdown".

I'm thinking that this bit of info serves at least to focus the problem.

John Pritchard