Solved

How do I force a re-draw?

Posted on 1998-09-15
9
214 Views
Last Modified: 2010-05-18
I'm making a 'Game of Life' Java swing component.

I've got it to the stage where the 'step' (one round of the game) command runs fine, but when I try to set up the 'run' command (which just iterates step until the stop button is pressed), the component freezes.

I'm assuming that this is because the redraw 'thread' which is spawned has a very low priority.  I basically want to 'force' a redraw.

I've toyed around with putting things in seperate threads, etc, and suspending them, but I haven't had much luck, and it occurs to me that a redraw-forcing option would really be a good idea.

Thanks for the help.
0
Comment
Question by:sstephens
  • 6
  • 3
9 Comments
 
LVL 3

Accepted Solution

by:
mjenkins earned 200 total points
ID: 1224269
Just call repaint( ms ) where ms is the timeout in milliseconds.
This version of repaint causes the repaint request to be put on the queue for no longer than the timeout allowed.

There's tyhe pat answer for your problem. I suspect, though that the real problem lie in your run() method. If you have a continuous loop, you may wish to call Thread.sleep() or Thread.yield() to give other threads a chance to run.
0
 
LVL 3

Expert Comment

by:mjenkins
ID: 1224270
If that doesn't solve your problem, post the code and I'll help walk you through it.
0
 

Author Comment

by:sstephens
ID: 1224271
I've tried both of those things - neither really worked satisfactorally.

I actually solved the problem - the following code replaces repaint():

Graphics g = getGraphics();
update(g);
g.dispose;

for some reason this works, whereas the other stuff didn't!

However, this raises another problem - I've also got a 'stop' button, and I want the pressing of this button to intercept the loop.

Unfortunately, it doesn't - the loop is occupying ALL of the JVM's time.

Would it work if I started a seperate thread for the loop, and another to watch the stop button, and then got the stop button thread to kill the loop thread?

      -Shane
0
 
LVL 3

Expert Comment

by:mjenkins
ID: 1224272
If the loop is occupying all of the time, the problem is in your loop. I wouldn't recommend the work around that you are implementing. It is not a good idea to call update yourself. Let repaint take care of calling update. Just fix your loop so that the AWT thread has enough time to do its job.

My offer still stands, post the code and I will walk through it with you.
0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 

Author Comment

by:sstephens
ID: 1224273
OK - that would be good.  I don't have the code on this machine, however, so I'll try and reconstruct a 'cut-down' version:

class gameoflife extends JFrame implements ActionListener {

    boolean runflag = false;

public void main (String args[]) {
    //implements all the buttons, and an array of JPanels to
    //color white or black
}

public void actionPerformed (ActionEvent e) {
    if (e.getSource().equals("Step"))
      singlestep();
    if (e.getSource().equals("Start"))
      startrun();
    if (e.getSource().equals("Stop"))
      setFlag(false);
}

public void singlestep {
    //code for calculating what cells are 'on', and what cells
    //are 'off'.

    //code for switching the background colour dependant upon
    //whether cell is on or off.

    //repaint();  <- but I replaced this with:
    Graphics g = getGraphics();
    update(g);
    g.dispose();

    //repaint works fine for single steps, but freezes in
    //multiple steps.
    //btw, I tried repaint(100), but this did NOT repaint
}

public void setflag(boolean val) {
      runflag = val;
}

public void startrun() {

    //make appropriate buttons disabled/enabled

    setflag(true);

    while (runflag) {
      singlestep();
    }

    //make appropriate buttons enabled/disabled

}
            
//There's also a method for turning white cells black and black cells white when they're clicked on.  I didn't extend JPanel to provide for this capability, instead I wrote a method for THIS object to listen to mouseclicks and change the background of the JPanels accordingly.

}

Anyway, that's it. I apologise in advance for any mistakes.

Just out of curiosity, what's so bad about calling update() myself?  I mean, it's my computer and my program!  It's also a provided method (as is getGraphics()).

I suppose that the problem is that there's not really enough literature about 'correct' programming design (if update() IS 'bad' programming design), so people are forced to try and figure out how to get what they want done the best way they can.

Anyway, thanks for the help

      -Shane
0
 
LVL 3

Expert Comment

by:mjenkins
ID: 1224274
Let me have a chance to look at your code before I respond, but I did want to answer: "what's so bad about calling update() myself? I mean, it's my computer and my program!  It's also a provided method (as is getGraphics())."

The problem is that the awt stuff is not thread safe. It is assumed by the designers that all calls to update() and paint() -- and a couple of other Component methods -- are invoked from the same thread, the AWT thread. The same goes for GUI events. It is assumed that all AWT events are passed in the Event dispatch thread.

If you make calls to these methods from another thread, you could easily end up either corrupting your component objects or causing a deadlock! The repaint method really just causes update to be called from the AWT thread with the same basic call you are making.

That is why I suspect that there is a problem with your thread. I will get back to you later with more after I have a chance to look through your code.
0
 
LVL 3

Expert Comment

by:mjenkins
ID: 1224275
sstephens,

here is a simple class that does what you want. It doesn't have the life rules in it or anything but it constantly updates the background color of the buttons.

import java.awt.*;

public class Life2
        extends Panel
        implements Runnable
{
        private Button b[] = new Button[4];
        private boolean f[] = { true,false,true,false };
        boolean keepAlive = true;

        public static void main( String args[] )
        {
                Frame f = new Frame( "Life2" );
                Life2 foo = new Life2();
                f.add( foo );
                f.setSize( 400,400 );
                f.setVisible( true );
                new Thread( foo ).start();
        }

        public Life2()
        {
                add( b[0] = new Button("b0") );
                add( b[1] = new Button("b1") );
                add( b[2] = new Button("b2") );
                add( b[3] = new Button("b3") );
        }

        public void run()
        {
                while( keepAlive )
                {
                        step();
                        try{
                        Thread.sleep(100);
                        }
                        catch( Exception e ) {}
                }
        }

        public void step()
        {
                for( int i = 0; i < 4; i++ )
                {
                        if( f[i] )
                                b[i].setBackground( Color.blue );
                        else
                                b[i].setBackground( Color.red );
                        f[i] = !f[i];
                }
                repaint(1);
        }
}

The key login is in the run() method. We call step() in a loop. That allows the buttons state to be changed and a repaint request queued up. Then the new thread sleeps for a tenth of a second to allow the AWT thread to do its thing. No problem. In your example, you never Sleep. The loop keeps running without ever giving up control to the AWT thread. Therefore, no repaints.

I also didn't see a run() method or a declaration for Runnable, but I assume that they are there in the real thing.

Does that explain it?
0
 
LVL 3

Expert Comment

by:mjenkins
ID: 1224276
The first sentence shoud read:

The key is in the run() method.

I don't know what happened?????
0
 

Author Comment

by:sstephens
ID: 1224277
..Yes and no..

I tried various things using a run() method, and implementing the runnable interface, but couldn't get them to work.  I'll toy around a bit more, tho', and try to do things the way you've set them up.  I think the difference is that I wasn't using Thread.sleep() - does this command automatically cause the active thread to sleep???

The program in it's current state doesn't use run() - that's why it wasn't included when I sent it to you.

Thanks for the advice, though - I think this will work now.

      -Shane
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

Introduction Java can be integrated with native programs using an interface called JNI(Java Native Interface). Native programs are programs which can directly run on the processor. JNI is simply a naming and calling convention so that the JVM (Java…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
Video by: Michael
Viewers learn about how to reduce the potential repetitiveness of coding in main by developing methods to perform specific tasks for their program. Additionally, objects are introduced for the purpose of learning how to call methods in Java. Define …
Viewers will learn about if statements in Java and their use The if statement: The condition required to create an if statement: Variations of if statements: An example using if statements:

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now