java你图形界面你喜欢的运动,Java图形界面基础实战项目讲解以及构造方法的介绍...

如何实现下大雪

还记得之前做的满天星的项目吗?还记得怎么实现吗?忘记了回去看看,再把代码写一遍,在讲解满天星项目的时候,我在最后提到过要怎么让这些星星落下来,不知大家去实现过了没?不过这些都不是重点,今天我将带大家一起来做一遍。

好的,直接开讲,还是老样子,我们先把项目分解,要分成那几步去做

1.实现满天星

2.让星星落下来

随着你的编程能力越来越强,每一步能够驾驭的代码会越来越多。

下面的代码实现了满天星,又加上了线程,在线程里加入了不断循环,延时和重画,这些都是我们已经学习过的内容,下面我要放上源代码了,最好是自己去实现,若是不行,再回头看看还有哪一个点是不清楚的

import java.awt.*;

public class MySnow {

public static void main(String[] args) {

// TODO Auto-generated method stub

Frame w = new Frame();

w.setSize(1024,768);

w.setBackground(Color.BLACK);

MySnowPanel msp = new MySnowPanel();

w.add(msp);

Thread t = new Thread(msp);

t.start();

w.show();

}

}

class MySnowPanel extends Panel implements Runnable{

public void paint(Graphics g){

g.setColor(Color.WHITE);

for(int i=0;i<300;i++){

g.drawString("*", (int)(Math.random()*1024),(int)(Math.random()*768));

}

}

@Override

public void run() {

// TODO Auto-generated method stub

while(true){

try{

Thread.sleep(30);

}catch(Exception e){}

repaint();

}

}

}

925fecfeec4f9111ce6cbc061e0c42e6.png

如果你的代码和我的相似,那么最后的结果是不是和我一样最后是雪花满屏幕的乱飞,是风太大吗?当然还是要思考一样为什么会这个样子,道理还是很简单,看看最后的repaint()的方法,每次重画全新的300颗星星的位置全部都会重置。

如果喜欢每颗星星都像小球一样,缓慢的落下来,我们就不能再paint方法里生成随机数来确定每一个坐标,而是需要提前准备好300个随机的坐标,并且将这些随机数存下来,每次去修改300个y坐标。然而现在我们有两个问题要解决:一是我们需要300个X坐标和Y坐标,也就是说我们要声明600个变量来存放预先生成的随机数;二是我们需要在paint方法运行前产生所有的随机数。产生大量相同类型的变量,用数组,事实上数组还有一个原则——通常将含义相同的变量定义为一个数组。数组其实也就是批量声明变量的工具

class MySnowPanel extends Panel implements Runnable{

int x[]=new int[300];

int y[] = new int [300];

public void paint(Graphics g){

g.setColor(Color.WHITE);

for(int i=0;i<300;i++){

g.drawString("*", (int)(Math.random()*1024),(int)(Math.random()*768));

}

}

@Override

public void run() {

// TODO Auto-generated method stub

while(true){

try{

Thread.sleep(30);

}catch(Exception e){}

repaint();

}

}

}

仔细看一下数组的定义,很像生成对象的代码,一个重要重要的标志就是new,这说明是在堆里申请一个空间,不同之处在于[],这是数组特有的标志。

有了这600个变量,我们需要解决两个问题,即将随机数一次性装到这些变量中。

class MySnowPanel extends Panel implements Runnable{

int x[ ]=new int[300];

int y[ ] = new int [300] ;

for(int i=0;i<300;i++){

x[i]=(int)(Math.random()*1024);

y[i]=(int)(Math.random()*768);

}

public void paint(Graphics g){

g.setColor(Color.WHITE);

for(int i=0;i<300;i++){

g.drawString("*", (int)(Math.random()*1024),(int)(Math.random()*768));

}

}

@Override

public void run() {

// TODO Auto-generated method stub

while(true){

try{

Thread.sleep(30);

}catch(Exception e){}

repaint();

}

}

}

如果按照这样子修改,把新的代码加载paint的方法之上,看看行不行,好像这段代码有问题,在我的eclipse中还没有编译就直接报错了,是不是和我一样

c43875a09b6c94e76ef40c4fdde7513c.png

那我们来分析一下为啥子不可以,我把新的代码放到了数组声明的下面,在paint方法的上面,这也就是告诉编译器,变量声明和方法声明处在了同一级,MySnowPanel类的下一层,这是不被允许的,也就难怪eclipse会报错了,类里面是不可以有语句的,在Java程序中,第一层是类,类里面就是第二层,允许有变量和方法,第三层在方法里面,允许有变量和语句,不过例外总是存在,会在后面提到,不过现在就不考虑了,免得混淆。

fc613b4a3a652f1095045ab48709171b.png

看来我们需要找一个方法,在这个方法里面赋值,要求这个方法的运行在paint()被调用前。我们知道paint()方法第一次被调用的是窗体显示的时候,我们用w.add(mp)将MySnowPanel放到窗体上,我们大体可以认为这个操作之后,paint方法就已经被调用了,所以我们需要在w.add(mp)这个操作前赋值,但是不能将赋值操作放到main里,因为main里x和y不可见,还必须放到MySnowPanel里。

有了这样的分析,我们完全就可以这样做,把赋值语句放到aaa里,在main里调用aaa方法

class MySnowPanel extends Panel implements Runnable{

int x[ ]=new int[300];

int y[ ] = new int [300] ;

public void aaa(){

for(int i=0;i<300;i++){

x[i]=(int)(Math.random()*1024);

y[i]=(int)(Math.random()*768);

}

}

public void paint(Graphics g){

g.setColor(Color.WHITE);

for(int i=0;i<300;i++){

g.drawString("*", x[i],y[i]);

}

}

@Override

public void run() {

// TODO Auto-generated method stub

while(true){

try{

Thread.sleep(30);

}catch(Exception e){}

repaint();

}

}

现在eclipse就不会报错了吧,不过这代码我看着不舒服,不知道各位看了什么感觉,Java考虑到这种对象一出现就需要的操作还很多,于是设计了一个机制,叫做构造方法。首先明确的是设计者定义了一个方法,一个特别的方法,举Frame w = new Frame()这句话,我们看到这里有个小括弧,好像每一个生成对象的语句都有一个小括弧在这个位置上,包括小括弧很像是方法的调用,没错,这个地方确实调用了一个方法,这个方法的名字就是类名,是不是很特别,也就是说,假如你声明了一个方法,名字就是类名,那么这个方法就会在生成对象的时候被自动调用。还有个问题,声明这个方法的时候,返回值应该是什么?按照调用来,应该是w类型,就是这个类,这是你改变不了得,索性定义这机制的人就规定构造方法声明的时候不能用返回值。

class MySnowPanel extends Panel implements Runnable{

int x[ ]=new int[300];

int y[ ] = new int [300] ;

//构造方法

public MySnowPanel(){

for(int i=0;i<300;i++){

x[i]=(int)(Math.random()*1024);

y[i]=(int)(Math.random()*768);

}

}

public void paint(Graphics g){

g.setColor(Color.WHITE);

for(int i=0;i<300;i++){

g.drawString("*", x[i],y[i]);

}

}

@Override

public void run() {

// TODO Auto-generated method stub

while(true){

try{

Thread.sleep(30);

}catch(Exception e){}

repaint();

}

}

定义下来,构造方法和类同名,没有返回值的方法,它会在类生成对象的同时被自动调用,肯定有人会问那么构造方法到底是干嘛的,一个广泛的流传的解释是,构造方法是用来初始化的。没错,大多数情况下构造方法是用来初始化的,就像这个案例,我们用构造方法给数组填上初值,但是这个解释我并不认同,它是干嘛的,要看你在里面写了什么代码,构造方法只是一个机制,让你在对象生成的那一刻瞬间有机会做一些你想要做的事情而已。

好了!我们有300个随机的X和300个堆积的y,下一步要在线程循环里让每个y的值加一。别忘了,落到屏幕下面的雪花,需要让它回到屏幕上方,这样才能产生连续不断的下雪场面。

下面我把最后的代码放上来

import java.awt.*;

public class MySnow {

public static void main(String[] args) {

// TODO Auto-generated method stub

Frame w = new Frame();

w.setSize(1024,768);

w.setBackground(Color.BLACK);

MySnowPanel msp = new MySnowPanel();

w.add(msp);

Thread t = new Thread(msp);

t.start();

w.show();

}

}

class MySnowPanel extends Panel implements Runnable{

int x[ ]=new int[300];

int y[ ] = new int [300] ;

//构造方法

public MySnowPanel(){

for(int i=0;i<300;i++){

x[i]=(int)(Math.random()*1024);

y[i]=(int)(Math.random()*768);

}

}

public void paint(Graphics g){

g.setColor(Color.WHITE);

for(int i=0;i<300;i++){

g.drawString("*", x[i],y[i]);

}

}

@Override

public void run() {

// TODO Auto-generated method stub

while(true){

try{

for(int i=0;i<300;i++){

y[i]++;

if(y[i]>768){

y[i]=0;

}

}

Thread.sleep(30);

}catch(Exception e){}

repaint();

}

}

}

看看结果

8dbae21483a98c56fb6d64d466a078be.png

到这里了,你可以写出很多东西了,比如小球的碰撞,雪花随风飘扬,利用三角函数可以让小球做抛物运动等等,还可以用键盘控制小球,或者说天上下的不是雪花而是字母,在落地前你按着键盘字母会消失,但是这已经是一个打字母的游戏了,不过这个是下一期的更新内容,还是请大家多多练习,多多理解。今天就到这里,下期再见!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值