Solved

How do I force a re-draw?

Posted on 1998-09-15
9
251 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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
 

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

PeopleSoft Has Never Been Easier

PeopleSoft Adoption Made Smooth & Simple!

On-The-Job Training Is made Intuitive & Easy With WalkMe's On-Screen Guidance Tool.  Claim Your Free WalkMe Account Now

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Certificat to iSeries KeyStore 1 31
web project error add remove 1 84
Setup GlassFish 4 55
Running JavaFX on the Raspberry Pi 27 295
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…
In this post we will learn how to connect and configure Android Device (Smartphone etc.) with Android Studio. After that we will run a simple Hello World Program.
This tutorial covers a practical example of lazy loading technique and early loading technique in a Singleton Design Pattern.
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …
Suggested Courses

751 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