views:

638

answers:

1

I've got a problem which I just can't seem to get around involving a small animation. For a project we are designing a J9 application to run on a PDA (DELL Axim X51). The problematic code (shown below) is when a mouse click is detected to run a small animation in a nested panel. If the animation is run independently of the mouse click, it works fine and repaints perfectly. When the method is called when a mouse click is recognized the repaint at every animation interval us ignored and only once the animation is completed will the panel be repainted.

I think it might have something to do with when a mouse click is recognized the application is synchronized with itself stopping any internal method calls to paint OR that the paint operation does not have high enough priority over the mouse click.

My code:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Panel;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class StatusLoader extends Panel implements Runnable{

        int progress;

        public static void main(String[] args) {
                Frame f = new Frame();
                StatusLoader  mp = new StatusLoader();
                mp.setBackground(Color.yellow);
                f.add(mp);

                f.setSize(300,300);
                f.show();       
                f.addWindowListener(new WindowAdapter() {            
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
                mp.start();
        }

        public void start(){
                Thread t = new Thread(this);
                t.run();

        }

        public void run(){
                for (int i = 0; i < 10; i++) {
                        progress+=10;
                        this.repaint(0);
                        System.out.println(i);
                        try{
                                Thread.sleep(100);
                        }catch(InterruptedException ex){}
                }
        }

        public void paint(Graphics g){
                System.out.println("called repaint");
                g.setColor(Color.red);
                g.setFont(new Font("Sansserif",2,24));
                FontMetrics fm = g.getFontMetrics();
                int stringWidth = fm.stringWidth("Loading");
                g.drawString("Loading", getWidth()/2-stringWidth/2, getHeight()/2);
                g.setFont(new Font("Sansserif",2,12));
                fm = g.getFontMetrics();
                stringWidth = fm.stringWidth("Map ziles for the new zoom level");
                g.drawString("Map tiles for the new zoom level", getWidth()/2-stringWidth/2, getHeight()/2+30);
                g.drawRect(getWidth()/2-100, getHeight()/2+60, 200, 10);
                g.setColor(Color.blue);
                g.fillRect(getWidth()/2-100, getHeight()/2+60, progress*2, 10);
        }

}
+2  A: 

In StatusLoader.start, you use Thread.run instead of Thread.start. That means StatusLoader.run is executed on the events thread, which is a Very Bad Thing. Change it to t.start().

Pesto
Ha! Perfect, thanks :)