以下是《java2实用教程(第三版)》(耿祥义,张跃平著)例子7.24的源码。说明:
该例子通过扩展Button类自治一个竖状的按钮来模仿交通信号灯,通过重写update()方法,有选择地清除按钮上以前所绘制的内容。 但是在运行的时候,我发现当单击鼠标速度很快时,上一次所绘的内容将不会被清除,既同时显示两个颜色的交通灯。单击速度放慢后则不会出现这个问题。
在同时显示两个交通灯的情况下,窗口失去焦点再获得焦点将变为一个交通灯。 请问这个现象是什么原因造成的?import java.awt.*;
import java.awt.event.*;
class MyButton extends Button implements ActionListener{
int x=10,y=10,i=0;
Color color[]={Color.red,Color.yellow,Color.green};
Color c=color[0];
MyButton(){
setSize(38,85);
setBackground(Color.cyan);
addActionListener(this);
}
public void paint(Graphics g){
g.setColor©;
g.fillOval(x,y,20,20);
}
public void update(Graphics g){
g.clearRect(x,y,20,20);
paint(g);
}
public void actionPerformed(ActionEvent e){
i=(i+1)%3;
c=color[i];
y=y+23;
if(y>56)y=10;
repaint();
}
}
class WindowCanvas extends Frame{
WindowCanvas(){
MyButton button=new MyButton();
setLayout(null);
add(button);
button.setLocation(30,30);
setBounds(60,125,100,200);
setVisible(true);
validate();
}
}
public class Example7_24{
public static void main(String args[]){
new WindowCanvas();
}
}
该例子通过扩展Button类自治一个竖状的按钮来模仿交通信号灯,通过重写update()方法,有选择地清除按钮上以前所绘制的内容。 但是在运行的时候,我发现当单击鼠标速度很快时,上一次所绘的内容将不会被清除,既同时显示两个颜色的交通灯。单击速度放慢后则不会出现这个问题。
在同时显示两个交通灯的情况下,窗口失去焦点再获得焦点将变为一个交通灯。 请问这个现象是什么原因造成的?import java.awt.*;
import java.awt.event.*;
class MyButton extends Button implements ActionListener{
int x=10,y=10,i=0;
Color color[]={Color.red,Color.yellow,Color.green};
Color c=color[0];
MyButton(){
setSize(38,85);
setBackground(Color.cyan);
addActionListener(this);
}
public void paint(Graphics g){
g.setColor©;
g.fillOval(x,y,20,20);
}
public void update(Graphics g){
g.clearRect(x,y,20,20);
paint(g);
}
public void actionPerformed(ActionEvent e){
i=(i+1)%3;
c=color[i];
y=y+23;
if(y>56)y=10;
repaint();
}
}
class WindowCanvas extends Frame{
WindowCanvas(){
MyButton button=new MyButton();
setLayout(null);
add(button);
button.setLocation(30,30);
setBounds(60,125,100,200);
setVisible(true);
validate();
}
}
public class Example7_24{
public static void main(String args[]){
new WindowCanvas();
}
}
我去掉了,就不会出现你点的很快的时候,显示两个灯的情况了
把update()注释掉效果是一样的
repaint()会自动调用update()和是否改写update()也不矛盾,所以我觉得问题不是出在这里。回3楼:
把actionPerformed方法里的repaint();去掉后,虽然是不会出现同时两个灯的现象,但是如果点击太快回没有反应,再次点击灯会连续变化两次。
具体调用过程是:repaint()调用update(),update()默认执行清空以前所绘内容并调用paint()回6楼:
没有。如果你有解决方法或是想法的话欢迎发上来讨论。
import java.awt.*;
import java.awt.event.*;
class MyButton extends Button implements ActionListener{
int x=10,y=10,i=0;
Color color[]={Color.red,Color.yellow,Color.green};
Color c=color[0];
MyButton(){
setSize(38,85);
setBackground(Color.cyan);
addActionListener(this);
}
public void paint(Graphics g){
g.setColor(c);
g.fillOval(x,y,20,20);
}
public void update(Graphics g){
System.out.println("执行update()");//new
g.clearRect(x,y,20,20);
System.out.println("执行清除结束");//new
paint(g);
System.out.println("执行重绘结束");//new
}
public void actionPerformed(ActionEvent e){
i=(i+1)%3;
c=color[i];
y=y+23;
if(y>56)y=10;
repaint();
}
}
class WindowCanvas extends Frame{
WindowCanvas(){
MyButton button=new MyButton();
setLayout(null);
add(button);
button.setLocation(30,30);
setBounds(60,125,100,200);
setVisible(true);
validate();
}
}
public class Example7_24{
public static void main(String args[]){
new WindowCanvas();
}
}每一次单击这三句都会打印,也就是说清除和重绘都是执行了的。可是同时显示两个灯的问题依然存在。
我实在是没辙了。
改下update就好使了...import java.awt.*;
import java.awt.event.*;
class MyButton extends Button implements ActionListener{
int x=10,y=10,i=0;
Color color[]={Color.red,Color.yellow,Color.green};
Color c=color[0];
Image image;
MyButton(){
setSize(38,85);
setBackground(Color.cyan);
addActionListener(this);
}
public void paint(Graphics g){
g.setColor(c);
g.fillOval(x,y,20,20);
}
public void update(Graphics g){
image = this.createImage(1024, 768);
if (image != null) {
Graphics g2 = image.getGraphics();
paint(g2);
g2.dispose();
g.drawImage(image, 0, 0, null);
} else {
paint(g);
}
paint(g);
}
public void actionPerformed(ActionEvent e){
i=(i+1)%3;
c=color[i];
y=y+23;
if(y> 56)y=10;
repaint();
}
}
class WindowCanvas extends Frame{
WindowCanvas(){
MyButton button=new MyButton();
setLayout(null);
add(button);
button.setLocation(30,30);
setBounds(60,125,100,200);
setVisible(true);
validate();
}
}
public class Example7_24{
public static void main(String args[]){
new WindowCanvas();
}
}
g.clearRect(x,y,20,20);
语句清除的是一个长宽都为20的矩型,它只能覆盖一个交通灯大小的区域,而当你快速单击的时候,实际上相当于两次执行了actionPerforemd方法,而执行的清除操作只对当前交通灯有效,对更前一次的时候是无效的,所以,第一次单击时的交通灯就没有被清除.如果你把清除操作修改成覆盖三个交通灯的矩形,例如
g.clearRect(x,y,80,80);
就不会出这个问题了
因为两次单击相隔时间太短,当你第一次单击的update还未调用时,第二次单击已经发生,此时坐标(x,y)已经变成了第二次第二次时的值,所以,起不到清除第一次时交通灯的作用.
SWING的刷新问题都是双缓冲来解决的..