您的位置:首页 > 编程语言 > Java开发

Java图形界面基础实战项目讲解以及构造方法的介绍

2016-04-06 17:36 726 查看

如何实现下大雪

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

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

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();
}
}

}




如果你的代码和我的相似,那么最后的结果是不是和我一样最后是雪花满屏幕的乱飞,是风太大吗?当然还是要思考一样为什么会这个样子,道理还是很简单,看看最后的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中还没有编译就直接报错了,是不是和我一样



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



看来我们需要找一个方法,在这个方法里面赋值,要求这个方法的运行在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();
}
}
}


看看结果



到这里了,你可以写出很多东西了,比如小球的碰撞,雪花随风飘扬,利用三角函数可以让小球做抛物运动等等,还可以用键盘控制小球,或者说天上下的不是雪花而是字母,在落地前你按着键盘字母会消失,但是这已经是一个打字母的游戏了,不过这个是下一期的更新内容,还是请大家多多练习,多多理解。今天就到这里,下期再见!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 界面 图形 编程