1

I'm creating a simple game and I'd like to repaint the board after every move. So, after I call move(), what I would like to do is this: (by the way, a View is a JComponent that holds pieces; since the number of pieces has changed after the move, it needs to be repainted)

for(View v : views){            
        v.repaint();
    }

It's not working. When I call repaint() on a single View, it works fine. I tried using paintImmediately, and revalidate, and update... nothing works within the loop.

Any ideas? Thanks in advance.

EDIT: I should add that repaint() does get called when the window is resized, so I know that View's paintComponent method is valid and works. It's just not being called from the loop. When the debugger steps through the loop, it does not enter repaint() and nothing happens to the screen.

dj18
  • 384
  • 3
  • 7
  • 19
  • There is nothing wrong with the source that you have included. It seems likely that you need to include more of the source in question. – DwB Jan 12 '11 at 17:16
  • Possible duplicate of http://stackoverflow.com/questions/4120528/repaint-in-a-loop – CoolBeans Jan 12 '11 at 17:25
  • I read that thread - that's from where I got the idea to try paintImmediately. As for posting more code, what should I post? The paintComponent method works fine (see edited question). – dj18 Jan 12 '11 at 17:44
  • Is that loop on the EDT? – justkt Jan 12 '11 at 18:09
  • Umm...I'm not so experienced that I know what you mean by that. It's not a multi-threaded application, if that's your question. I have a MouseListener that listens to know which View/JComponent was clicked, calls move() based on which View was selected, and then calls the loop to repaint all the components. – dj18 Jan 12 '11 at 18:19
  • read http://java.sun.com/products/jfc/tsc/articles/painting/index.html, the MouseListener runs on the Event Dispatch Thread so the components won't actualyl be painted until the MouseListener is finished and the EDT moves on to process the update() request. – Kevin K Jan 12 '11 at 18:43
  • Also you mention 'it does not enter repaint()', have you checked that 'views' isn't empty? – Kevin K Jan 12 '11 at 18:45
  • 1. Thanks for the link; it's very informative. I tried to disable DoubleBuffering: no go. 2. "views" isn't empty: the debugger steps through the loop exactly the number of times it should, but when it hits the "repaint" statement, it just goes on to the next iteration. 3. And as far as the MouseListener finishing, the loop is the last statement in the listener. – dj18 Jan 13 '11 at 03:13

2 Answers2

1

Everything related to the UI must be called in the Event Dispatching Thread (EDT):

SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        for(View v : views){
            v.repaint();
        }
    }
});

You can also use invokeAndWait instead of invokeLater. You should read on the EDT if you want a responsive application.

For example, if you add an actionListener to a button, the code executed in that actionListener is executed in the EDT thread, so you must limit the process or you UI will stop responding.

Also, take a look to SwingUtilities.isEventDispatchingThread()

JPelletier
  • 2,049
  • 16
  • 23
0

Sometimes revalidate does not work if the nearest validateRoot is a JScrollPane. Not sure why. Try calling revalidate on the frame itself to see if that works. If it does, you have a problem with a validateRoot not properly validating your components. You only need to call revalidate once when the loop is finished.

Nemi
  • 3,011
  • 1
  • 26
  • 24