为什么Swing编程时画面会卡住

解决GUI编程中图象卡住现象,Swing线程机制

编写GUI界面时,经常会莫名其妙的,画面卡住了,严重的情况甚至黑屏了。为什么会这样呢?

当编写一个Swing程序时,就存在一条Swing事件分发线程(EDT),它区别于main线程。事件分发线程处理所有GUI操作,而它又是一个单一线程,所以就显得非常忙碌(如下图所示)。一旦事件分发线程太忙碌就会出现画面卡住不动的情况。我们在进行Swing编程时,应该把握好以下原则:

1、需要处理的GUI请求非常多,包括窗口移动、组件自动重绘、刷新,它很忙,所以任何与GUI无关的处理不要由EDT来负责

2、职责分明,任何GUI请求都应该在EDT中调用

           

一、任何与GUI无关的处理不要由EDT来负责

    要达到这种效果的方法有很多,这里只介绍一种,即自己开发一条新的线程来处理与EDT无关的复杂运行,或占用资源时间较长的运算。下面是一个例子,为了顺利播放一个绘制十个圆圈和十个正方形的动画.

下面那样不可以运行,会卡住:

public class Test extends JPanel{
        int x=10,y=10,time=10,i=0;
        public Test(){
        }
        public void paintComponent(Graphics g){
            super.paintComponent(g);
            for(int j=0;j<i;j++){
                g.drawOval(100+j*x, 200+j*y, 30, 30);
                g.drawRect(200+j*x, 100+j*y, 30, 30);
                                     //EDT运行到这里卡住了,因为Thread.sleep(1000)让它阻塞了一秒钟
                try{
                    Thread.sleep(1000);
                }catch(Exception e){}
            }
    }
        public void update(Graphics g){
            paint(g);
        }
 
        public static void main(String args[]){
            JFrame jf= new JFrame();
            jf.setBounds(100, 200, 500, 500);
            jf.setVisible(true);
            Test test = new Test();
            jf.add(test);
        }
}


   程序画一个动画,每隔一秒钟画一个圆和一个正方形,共画十个,但由于程序让EDT每次都阻塞一秒,EDT阻塞就无法正常绘制图象,画面就卡住了。办法是开发另一条线程,用他来“承担”阻塞这个重担,EDT每次只要重绘一下就行了。

开发另一条线程,动画就不卡了

package newpackage;
import javax.swing.*;
import java.awt.Graphics;
 
public class Test extends JPanel{
        int x=10,y=10,time=10,i=0;
        public Test(){
        }
        public void paintComponent(Graphics g){
            super.paintComponent(g);
            for(int j=0;j<i;j++){
                g.drawOval(100+j*x, 200+j*y, 30, 30);
                g.drawRect(200+j*x, 100+j*y, 30, 30);
         }
    }
        public void update(Graphics g){
            paint(g);
        }
 
        public static void main(String args[]){
            JFrame jf= new JFrame();
            jf.setBounds(100, 200, 500, 500);
            jf.setVisible(true);
            Test test = new Test();
            jf.add(test);
            Draw d = new Draw(test);
            d.start();
        }
}

//定义的另一条线程,Thread.sleep(1000),是让线程阻塞,此动作不能让EDT来做,不然会卡住

class Draw extends Thread{
    Test t;
    Draw( Test t){
        this.t = t;
    }
    public void run(){
            for(;t.i<t.time;t.i++){
                t.repaint();
                try{
                    Thread.sleep(1000);
                }catch(Exception e){}
         }
    }
}

二、任何GUI请求都应该在EDT中调用(下面这一段是从《think in java》中抄来的。)

(待续)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值