我的这段代码,为什么在主函数当中调用fun()函数,就能够达到我想要的效果,能一步一步显示出执行过程。
而当点击按钮时,同样是调用fun()函数,为什么就没有显示出执行过程呢???
具体执行请运行代码。
我觉得应该是repaint()函数内部执行原理不太了解。或者是那个Thread.sleep(1000)的问题???
总之,我是个初学者,请大家指教。
代码如下:public class Test extends JFrame implements ActionListener { public static void main(String[] args)
{
Test t = new Test();
t.fun();
System.out.println("End of Main");
} int x, y;
Button but;
public Test() {
setBounds(400, 100, 350, 200);
this.setLayout(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
but = new Button("OK");
but.setSize(40, 40);
add(but);
but.addActionListener(this);
x = y = 50;
setVisible(true);
}
public void paint(Graphics g) {
System.out.println("call paint()");
super.paint(g);
g.fillOval(x, y, 9, 9);
}
public void fun() {
for (int i = 0; i < 5; i++) {
x += 20;
repaint();
try { Thread.sleep(1000); }
catch (InterruptedException e) { e.printStackTrace(); }
}
}
public void actionPerformed(ActionEvent e) {
fun();
}
}
而当点击按钮时,同样是调用fun()函数,为什么就没有显示出执行过程呢???
具体执行请运行代码。
我觉得应该是repaint()函数内部执行原理不太了解。或者是那个Thread.sleep(1000)的问题???
总之,我是个初学者,请大家指教。
代码如下:public class Test extends JFrame implements ActionListener { public static void main(String[] args)
{
Test t = new Test();
t.fun();
System.out.println("End of Main");
} int x, y;
Button but;
public Test() {
setBounds(400, 100, 350, 200);
this.setLayout(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
but = new Button("OK");
but.setSize(40, 40);
add(but);
but.addActionListener(this);
x = y = 50;
setVisible(true);
}
public void paint(Graphics g) {
System.out.println("call paint()");
super.paint(g);
g.fillOval(x, y, 9, 9);
}
public void fun() {
for (int i = 0; i < 5; i++) {
x += 20;
repaint();
try { Thread.sleep(1000); }
catch (InterruptedException e) { e.printStackTrace(); }
}
}
public void actionPerformed(ActionEvent e) {
fun();
}
}
改成下面的直接调用: Test.this.paint(Test.this.getGraphics());但在绘制完成前,是不会相应其他事件的。
为什么改成paint()就没有以前的毛病了呢???
改成这样后,在执行按钮事件时,不响应其他事件,这个有其他的解决办法吗??望指点,谢谢!
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;import javax.swing.JFrame;public class Test extends JFrame implements ActionListener { public static void main(String[] args)
{
new Test();
}
Button but;
Oval ovalShap ;
public Test() {
ovalShap = new Oval();
setBounds(400, 100, 350, 200);
this.setLayout(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
but = new Button("OK");
but.setSize(40, 40);
add(but);
but.addActionListener(this);
setVisible(true);
fun();
}
public void paint(Graphics g) {
super.paint(g);
((Graphics2D)g).fill(ovalShap.getShape());
} public void fun() {
ovalShap = new Oval();
new Thread(new OvalRunnable(ovalShap, this)).start();
}
public void actionPerformed(ActionEvent e) {
fun();
}
}class Oval{
double x = 50, y = 50;
public void move(){
x += 20;
}
public Ellipse2D getShape(){
return new Ellipse2D.Double(x, y, 9, 9);
}
}class OvalRunnable implements Runnable{
Oval ovalShap ;
Component comp;
public OvalRunnable(Oval ovalShap, Component comp){
this.ovalShap = ovalShap;
this.comp = comp;
}
public void run() {
for (int i = 0; i < 5; i++) {
ovalShap.move();
comp.repaint();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
{
Test t = new Test();
t.fun();
System.out.println("End of Main");
for (int i=0; i<100; i++) { //主线程循环测试,看看主线程是否影响Swing线程
System.out.println("main" + i);
try {Thread.sleep(1000);} catch (Exception e) {}
}
} int x, y;
Button but;
public Test() {
setBounds(400, 100, 350, 200);
this.setLayout(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
but = new Button("OK");
but.setSize(40, 40);
add(but);
but.addActionListener(this);
x = y = 50;
setVisible(true);
}
public void paint(Graphics g) {
System.out.println("call paint()");
super.paint(g);
g.fillOval(x, y, 9, 9);
}
public void fun() {
for (int i = 0; i < 5; i++) {
x += 20;
repaint();
try { Thread.sleep(1000); }
catch (InterruptedException e) { e.printStackTrace(); }
}
}
public void actionPerformed(ActionEvent e) {
new Thread() { //用线程来执行,看看该线程是否影响Swing线程
public void run() {
fun();
}
}.start();
}
}
原因2L已经说了
repaint是发送一条消息到消息队列中,消息处理线程会处理该消息,它的内部会调用paint方法,而消息处理必须处理一条消息结束以后才会取下一条消息进行处理,这样,它在处理按钮事件消息的时候,就没法及时处理repaint消息,而当它处理完按钮事件以后再处理repaint消息的时候,因为repaint事件很短促,所有肉眼看不到中间的变化,只能看到最后一个repaint,所以也就看不见执行过程
而直接调用paint方法,并不需要发送消息,也就是说当前线程自己处理paint方法,所有没有发生延时,可以看到执行过程
所以,可以改用一个别的线程来执行run方法,这样按钮事件就可以立即返回,也就是按钮事件不用做sleep处理,很快就结束了,这样消息处理线程就可以有空处理线程发送的repaint消息,而线程是每sleep1秒才发送一个repaint消息,这样消息处理线程处理repaint消息中间就有事件间隙,所以可以看到每一次repaint的效果,也就是可能看到执行过程