2个类:
package thread;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.text.*;/**
 * 这是时钟的类,有2个方法,一个用于开始计时并刷新指针的位置,一个停止计时
 */
public class SecondCounterLockup extends JComponent{
    private boolean keepRunning;
    private String timeMsg;
    private int arcLen;
    private Font paintFont;
    public SecondCounterLockup() {
      this.paintFont=new Font("Sanserif",Font.BOLD,14);
        this.timeMsg="never started";
        this.arcLen=0;
    }
     /**
       * 开始计时并刷新指针位置
       */
    public void runClock(){        System.out.println("thread running runClock() is "+Thread.currentThread().getName());        DecimalFormat fmt=new DecimalFormat("0.000");
        long normalSleepTime=100;
        int counter=0;
        keepRunning=true;        while (keepRunning){            try {
                Thread.sleep(normalSleepTime);
            } catch (InterruptedException e) {
                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
            }            counter++;
           double counterSecs=counter*0.1;       //求得经过的总秒数
            timeMsg=fmt.format(counterSecs);
            arcLen=(((int)counterSecs)%60)*360/60;//求经过的总角度数
            repaint();        }
    }
     /**
      * 停止
      */
    public void stopClock(){
        keepRunning=false;
    }
   /**
     * 绘制时钟
     * @param g
     */
    public void paint(Graphics g) {
        System.out.println("thread that invoked paint() is "+Thread.currentThread().getName());        g.setColor(Color.BLACK);
        g.setFont(paintFont);
        g.drawString(timeMsg,0,15);        g.fillOval(0,20,100,100);
        g.setColor(Color.white);
        g.fillOval(3,23,94,94);
        g.setColor(Color.blue);
        g.fillArc(2,22,96,96,90,-arcLen);
    }}package thread;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;/**
 * 这个类很简单,把刚才那个时钟类添加到面板上,再创建一个开始按钮一个停止按钮,然后把所有
 * 组件加到一个窗体上并显示
 */
public class SecondCounterLockupMain extends  JPanel{
    private SecondCounterLockup sc;
    private JButton startB;
    private JButton stopB;    public SecondCounterLockupMain() {
        this.sc = new SecondCounterLockup();
        startB=new JButton("Start");
        stopB=new JButton("Stop");
        stopB.setEnabled(false);
        startB.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e) {
                startB.setEnabled(false);
                sc.runClock();
                stopB.setEnabled(true);
                stopB.requestFocus();
            }        });        stopB.addActionListener(new ActionListener()
        {
           public void actionPerformed(ActionEvent e) {
                stopB.setEnabled(false);
                sc.stopClock();
                startB.setEnabled(true);
                startB.requestFocus();
            }
        });        JPanel innerButtonP=new JPanel();
        innerButtonP.setLayout(new GridLayout(0,1,0,30));
        innerButtonP.add(startB);
        innerButtonP.add(stopB);
        JPanel buttonP=new JPanel();
        buttonP.setLayout(new BorderLayout());
        buttonP.add(innerButtonP,BorderLayout.NORTH) ;        this.setLayout(new BorderLayout(100,100));
        this.setBorder(new EmptyBorder(20,20,20,20));
        this.add(buttonP, BorderLayout.WEST);
        this.add(sc,BorderLayout.CENTER);    }    public static void main(String args[]){
          SecondCounterLockupMain scm=new SecondCounterLockupMain();
        JFrame f=new JFrame("second counter lockup");
        f.setContentPane(scm);
        f.setSize(320,200);
        f.setVisible(true);
        f.addWindowListener(new WindowAdapter()
        {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });        }
}
现在问题是时钟并不走字,书上的解释是系统的线程AWT-EventQueue-0在runClock中循环时处于繁忙状态,因此无暇进行绘制时钟,这我就不明白了,它在runClock中也是顺序调用的,没有repaint完怎么会进入下一次循环呢,请高手指点迷津。

解决方案 »

  1.   

    public SecondCounterLockupMain() {
            this.sc = new SecondCounterLockup();
            startB=new JButton("Start");
            stopB=new JButton("Stop");
            stopB.setEnabled(false);
            startB.addActionListener(new ActionListener()
            {
                public void actionPerformed(ActionEvent e) {
                    startB.setEnabled(false);
                   // 更改!
                    new Thread()
                    {
                     public void run()
                     {
                     sc.runClock();
                     }
                    }.start();
                    
                    stopB.setEnabled(true);
                    stopB.requestFocus();
                }        });
      

  2.   

    它在runClock中也是顺序调用的,没有repaint完怎么会进入下一次循环呢,请高手指点迷津。------------------
    它确实有repaint完之后再进入下一次循环,但是SecondCounterLockup 是嵌在SecondCounterLockupMain 里面的,由于[开始按钮]的sc.runClock();使它陷入无限循环之中,所以SecondCounterLockupMain 界面也就没有更新过来.
    你可以其他均不变,添加下面一条语句:while (keepRunning){            try {
                    Thread.sleep(normalSleepTime);
                    
                } catch (InterruptedException e) {
                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
                }            counter++;
                // 添加此句
                if (counter % 100 == 0) break;
                
               double counterSecs=counter*0.1;       //求得经过的总秒数
                timeMsg=fmt.format(counterSecs);
                arcLen=(((int)counterSecs)%60)*360/60;//求经过的总角度数
                repaint();
            }就会发现它其实时间有走过了
      

  3.   

    呵呵
    sc.runClock();正在无限循环SecondCounterLockupMain 界面怎么更新?
      

  4.   

    连stopB按钮都无法复员过来,更不用说更新SecondCounterLockupMain 界面了. : )
      

  5.   

    嵌在窗体里就不能刷新了?-----------
    这里的刷新是指SecondCounterLockupMain 而非SecondCounterLockup.
    SecondCounterLockup 有刷新.但SecondCounterLockupMain 并未及时显示出来.
      

  6.   

    的确,把他放在一个单独的线程能够正常运行,书上的确有这样的例子。我只想问现在这种情况出现的原因。楼上说SecondCounterLockup 有刷新,于是我在paint方法里加上一行:  System.out.println("刷新了组件");但根本就未输出这句话,说明点击开始按钮后没有刷新此组件
      

  7.   

    http://java.sun.com/products/jfc/tsc/articles/painting/
      

  8.   

    to yuzl32:
      那篇文档很长,不知你要我看哪一部分才能解决问题,请指点迷津。
      

  9.   

    SendMessage和PostMessage区别. :)
      

  10.   

    yuzl32你到底会不会啊,会就请你说明白,不会就不要误导我了,哪有SendMessage和PostMessage这2个关键字,我看了那个网页,很长,也许就这一句话有用:The program invokes repaint() on the component, which registers an asynchronous request to the AWT that this component needs to be repainted.