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完怎么会进入下一次循环呢,请高手指点迷津。
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完怎么会进入下一次循环呢,请高手指点迷津。
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();
} });
它确实有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();
}就会发现它其实时间有走过了
sc.runClock();正在无限循环SecondCounterLockupMain 界面怎么更新?
这里的刷新是指SecondCounterLockupMain 而非SecondCounterLockup.
SecondCounterLockup 有刷新.但SecondCounterLockupMain 并未及时显示出来.
那篇文档很长,不知你要我看哪一部分才能解决问题,请指点迷津。