Skip to Main Content

Java SE (Java Platform, Standard Edition)

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Calling repaint() from invokeLater()

796262Oct 8 2009 — edited Oct 12 2009
Hello all,

I'm continuing my foray into using [invokeLater()|http://forums.sun.com/thread.jspa?threadID=5410578] to perform GUI changes. I'm posting this in a new Thread because it's a separate question from the other one (which has been answered), plus I just love awarding duke stars.

Here's the basic question: Say I'm doing a bunch of GUI "stuff" in a call to invokeLater() . But in the middle of all the GUI changes, I want to repaint a Component. I would have hoped that just putting the repaint where I wanted it to happen would do the trick, but it turns out that the call to repaint seemingly gets added after the rest of my GUI code in the invokeLater() call. I've created an SSCCE to demonstrate what I'm talking about:
import javax.swing.JPanel;
import javax.swing.JFrame;
import java.awt.Graphics;

public class RepaintTest{

	public RepaintTest(){

		//create a Panel that tells us when it is being repainted
		final JPanel repaintedPanel = new JPanel(){
			public void paintComponent(Graphics g){
				System.out.println("\nREPAINTING\n");
			}
		};

		//put the repaintedPanel in a Frame
		JFrame frame = new JFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.add(repaintedPanel);
		frame.setSize(100,100);
		frame.setVisible(true);

		//this just makes sure repaintedPanel is visible
		//otherwise repaint exits before paintComponent?
		try{
			Thread.sleep(2000);
		}
		catch(Exception e){}

		try{
			javax.swing.SwingUtilities.invokeLater(new Runnable() {
				public void run() {
					//do a bunch of pretend GUI stuff
					longMethod("one");
				
					//repaint the panel BEFORE continuing
					//or at least repaint at the same time as the other stuff
					repaintedPanel.repaint();

					//do the rest of the long-lasting GUI stuff
					longMethod("two");
				}
			});
		}
		catch(Exception e){
			e.printStackTrace();
		}
	}

	//pretend this is a method that does a bunch of GUI stuff
	public void longMethod(String name){
		for(int i = 0; i < 100; i++){
			System.out.println(name + ": " + i);
		}
	}

	public static void main(String [] args){
		new Thread(new Runnable() {
				public void run() {
					new RepaintTest();
				}
		}).start();
	}
}
I can see that repaint() is called when the JFrame first pops up, but let's say I want it to be also called between the calls to longMethod() inside invokeLater() . Currently, the repaint() always happens after the other two methods are completed. I'm not sure exactly why, but I'm imagining that repaint() uses another call to invokeLater() , which adds the actual painting command to the EDT after the commands I've placed there?

If I take out the invokeLater() , it does exactly what I'd want it to.

I hope I'm making sense, even if my question isn't a very smart one. I know I could probably use three separate calls to invokeLater(), but in my actual program that would require adding dozens (possibly hundreds) of those calls instead of using an all-encompassing call. So is there a way to make sure that the repaint happens before (or during) the code that comes after it?

Thanks again,

Kevin
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Nov 9 2009
Added on Oct 8 2009
10 comments
1,737 views