以前做画图板和五子棋敲代码一点思路都没有,在老师的引导下,最近在做弹球碰撞界
时,一步一步从简单到复杂来做,渐渐理出了思绪,真正理解了程序和代码之间的区别,就像胡总说的,代码不会,方法不会这都不要紧,关键是要有自己的思路,自己的想法,如果自己有好的想法,这样就可以跟着自己的思路去寻找自己需要的方法。。。
对于一个初学者来说,怎样做一个界面,首先列一个步骤,从1,2,3到。。。,一步一步完成,这样就会思路清晰很多
对于这次弹球碰撞界面:
步骤如下:
第一:画一个窗体界面,里面有按钮、中间面板、中间边框及画布
第二:能够画不留痕迹的多个小球,注意这里用到了动作监听器,及创建线程小球类及在动作监听器里面创建线程小球类对象
第三:能够随机小球出现时的位置和颜色
第四:边界碰撞和小球之间碰撞的方法的问题,注意
无论是边界碰撞,还是小球之间的碰撞,尽量不要用数字,
在解决小球之间碰撞时,要知道每时每刻每个小球的运动状态即位置
怎没解决呢 ,可以通过创建一个队列,将所有小球都加进去(因为每个小球对 象都是通过创建监听器方法
获得的,所以可以在此方法中添加,判断小球之间的碰撞时,将小球遍历出来就行了 )
第五:改变窗体大小时可以实现重绘,即得到每个小球的位置及颜色,解决方法是遍历小球,通过super.paint(g);通过g来调用画椭圆设置颜色的方法
注意,总共有3个画布,一个是中间面板获取得画布,一个是在线程小球类里面构造函数方法时传入的画布,一个就是重绘时执行paint(Graphics g)和super.paint(g)时
用途:中间面板获取的画布在BallFrame实现Runnable时,重写run()方法时有center.repaint()不停的调用重回方法时需要画布
小球线程类里面传入画布 是因为在BallFrame 里面定义了一个画布,有BallThread ball=new BallThread(g);目的其实是将BallFrame里面的画布传到类里面,可以绘出小球线程的运动
重绘时执行paint(Graphics g)的画布是为了保存改变窗体大小时,所设置的颜色方法和画的椭圆
第六: 双缓冲问题:因为每点击一次按钮就会出现一个小球,而且每间歇一次,多个小球调用,没走一次都调用屏幕(g.setColor()||g.fillOval());这样就会出现闪屏
解决方法是:我们可以创建一个可以获得画布的图片Image img=this.createImage(this.getPreferredSize().width,this.getPreferredSize().height);该图片可以获得画布
即:Graphics g=img.getGraphics(); 给画布设置图片背景:ImageIcon icon=new ImageIcon("MM.png");
g.drawImage(icon.getImage(), 1, 1,398,398,null);
双缓冲是在重绘的时候用到,即先把每个小球线程的位置先放到图片获取的画布上
然后将图片绘制在屏幕上
public void paint(Graphics g1)让g1.drawImage(img,0,0)
//重绘的方法
class Mypanel extends JPanel{
public void paint(Graphics g){
//为了解决闪屏问题,使用双缓冲:将center上的数据先保存到一张图片上,在保存到g上,目的减少对画布的调用
//创建一幅用于双缓冲的、可在屏幕外绘制的图像。
Image img=this.createImage(this.getPreferredSize().width,this.getPreferredSize().height);
//从图片上获取画布
Graphics2D g2 = (Graphics2D)img.getGraphics();
//直接调用父类中的方法,要在创建图标之前,否则会覆盖
super.paint(g2);
//创建图表对象
ImageIcon icon=new ImageIcon("MM.png");
//绘制背景
g2.drawImage(icon.getImage(), 1, 1,398,398,null);
//要把所有的小球的位置颜色重新绘制在窗体上当每次改变窗体大小的时候
//所以要把小球遍历出来
for(BallThread ball:BallThread.balls){
//而画布的子类画椭圆的方法是double型
Ellipse2D.Double oval=new Ellipse2D.Double(ball.x,ball.y,ball.ballsize,ball.ballsize);
g2.setColor(ball.color);
g2.fill(oval);
//g2.fillOval((int)ball.x, (int)ball.y,ball.ballsize,ball.ballsize);
}
//将图片绘制在屏幕上
g.drawImage(img, 0, 0, null);
}
}