如何在延时后或循环中正确调用repaint方法

文章探讨了在制作贪吃蛇游戏时添加通关切换效果时,使用Thread.sleep()和Timer进行延时的两种方法。作者分析了JavaGUI编程中的EventDispatchThread机制,指出直接使用repaint可能导致卡顿,并提供了通过单独线程或定时任务优化的方法。
摘要由CSDN通过智能技术生成

项目场景:

        在做贪吃蛇游戏时,加了个通关切换效果,用要延时技术!发现使用repaint方法+Thread.sleep()或repaint方法+Timer均可达到目的,但其中走了不少弯路,有必要将两种方式做个分析总结。


问题描述

  问题代码示例一:延迟调用repaint()

    public void test1(){
        try {
            Thread.sleep(1000);//延迟1秒执行
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        repaint();
    }

问题代码示例二:循环调用repaint()

    public void test2(){
        for(int i=0;i<10;i++){
            repaint();
        }
    }

        上述代码中,示例一直接休眠当前线程,会出现卡顿显现;示例二,只能得到最后一次调用repaint()结果。是什么原因造成的?如何解决呢?


原因分析:

       实际上,java在处理GUI任务时候会生成唯一线程用于管理分发事件,这个线程学名叫EDT(Event Dispatch Thread) 绘图事件派发线程,说白了,这个东西就是管着一堆事件。OK, repaint方法可以看作一个事件,因为你在调用repaint时候,系统不会立即执行paint()方法,而是把它加入到EDT中,等待执行。所以,我们在加入很多repaint()时,最终会合并一个只能看到最后结果的事件,或者主程序休眠,GUI程序也会休眠,再执行repaint()就会卡顿。因此,解决上述示例问题最好方法是给repaint()单独开线程或通过Timer的定时任务解决(实际也是单独一个线程)。


解决方案:

以问题示例一来说,延时1秒后执行,两种方式都要重写run()方法,具体解决方案如下

1、单独开线程实现:

    public void test1() {
	    Thread newThread=new Thread(new Runnable() {

		    @Override
		    public void run() {
			    try {
				    Thread.sleep(1000);
			    } catch (InterruptedException e) {
				    e.printStackTrace();
			    }
        //放要延迟执行的代码
			    repaint();
		    }
			
	    });
	    newThread.start();
    }

2、通过定时器实现

	public void test1() {
		Timer timer=new Timer();
		timer.schedule(new TimerTask() {

			@Override
			public void run() {
				//这里放延时执行的代码
				repaint();
				this.cancel();
				
			}
			
		}, 1000, 0);//延时1秒执行
	}

       问题示例二与示例一解决类似,当然有些情况下,repaint()一次调用paint()完成循环,要比循环repaint()调用paint()更好些!

        最后,repaint()方法在延迟后或循环中要想调到paint(),是需要单独建立通道,吃小灶的!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值