我们可以将Java中的绘图和现实中的挂画联系起来,如下图所示:
要想显示一幅画,则首先要有一个框架,在Java中为JFrame类。其次,在框架中嵌入图画,所有的视觉效果都是由图画呈现的。那么图画就相当于Java中的面板JPanel们的图形就在JPanel中显示。当然,我们可以随心所欲的在JPanel上乱涂乱画,只要你喜欢。
下面我们来演示一下如何运用Java绘制图形。
import javax.swing.JFrame;
public class TestTetrisGame {
public static void main(String[] args) {
// TODO Auto-generated method stub
JFrame frame = new JFrame("My Frame");//创建框架
//创建一个面板,我们的图形就在面板中绘制
TetrisPanel panel = new TetrisPanel();
frame.add(panel);//将面板嵌入到框架中
//点击X健关闭窗口,若不设置,将会隐藏掉窗口,
/可以打开资源管理器查看到javaw.exe
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 300);//将框架设置为长,高都为300像素
frame.setVisible(true);//将面板显示出来
}
}
现在我们有了一个相当于挂画一样的组合对象,运行程序会发现界面只是一个框架和空的面板,如下图所示:
这是因为我们没有在面板中绘制图形,在上面的程序中面板是通过JPanel生成的,由JPanel生成的面板都是空的,也就是上面没有绘制任何东西的面板。那么如何在面板中绘制图形呢?
很显然,我们需要有一个绘制好了图形的面板。如下所示:
import javax.swing.JFrame;
public class TestTetrisGame {
public static void main(String[] args) {
// TODO Auto-generated method stub
JFrame frame = new JFrame("My Frame");//创建框架
//创建一个面板,我们的图形 就在面板中绘制
TetrisPanel panel = new TetrisPanel();
frame.add(panel);//将面板嵌入到框架中
//点击X健关闭窗口,若不设置,将会隐藏掉窗口,
//可以打开资源管理器查看到javaw.exe
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 300);//将框架设置为长,高都为300像素
frame.setVisible(true);//将面板显示出来
}
}
然后将:
JPanel panel = new JPanel();
改为:
TetrisPanel panel = new TetrisPanel();
运行效果如下图所示:
现在我们知道如何在面板中显示图形了,在让这个图形运行起来前,我们先详细的了解一下上面代码的含义。
TestTetrisGame.java
import javax.swing.JFrame;
public class TestTetrisGame {
public static void main(String[] args) {
……
}
}
我们知道,Java中一切皆对象,程序的运行需要对象,对象的创建需要类。因此,程序设计的任务就是先设计类。
在上面的设计,有两个类,一个是实体类面板SnakePanel,一个是测试类TetsTetrisGame。首先我们来解析测试类TestTetrisGame:
在测试类中有一个main方法,我们称之为主方法,是程序执行的入口点。有此方法的类必须和文件名相同。我们推荐一个文件只有一个类,且文件名和类名相同(内部类除外)。
我们再来分析一下上面的程序,是否还有对象没有被抽取出来。在俄罗斯方块游戏中,有面板(专门显示图形),还有图形。很明显,我们仅仅有面板类,图形类却没有。因此,我们还可以继续优化俄罗斯方块游戏,将上面的TetrisPanel类拆分为面板类(TetrisPanel)和图形类(Shape)。
为了简化游戏,我们仅仅在面板中显示一个图形(方块),在后面将慢慢完善俄罗斯方块游戏。
下面是拆分后的类.
import java.awt.Graphics;
public class Shape {
//图形在面板中显示的坐标
int x, y;
//图形的宽度和高度
int width, hight;
//在x,y坐标处绘制图形
public void drawShape(Graphics g){
g.fillRect(x, y, width, hight);
}
}
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class TetrisPanel extends JPanel {
Shape shape; //表示面板类中存储着某个图形的信息
//显示面板时,此方法将被调用
protected void paintComponent(Graphics g) {
……
shape.drawShape(g);
}
}
import javax.swing.JFrame;
public class TesTetrisGame {
public static void main(String[] args) {
……
Shape shape = new Shape();
//初始化图形的坐标
shape.x = shape.y = 100;
shape.width = shape.hight = 10;
//创建一个面板,我们的图形就在面板中绘制
TetrisPanel panel = new TetrisPanel();
//将创建的图形传递给面板
panel.shape = shape;
……
}
}
我们运行程序可以得出和上面的结果一样,现在来剖析一下代码。
1、在测试类中,我们首先创建一个图形对象,并初始化对象中的属性
Shape shape = new Shape();
shape.x = shape.y = 100;
2、创建面板对象,并将上面创建的图形对象传递给面板
TetrisPanel panel = new TetrisPanel();
panel.shape = shape;
3、面板显示时,(paintComponent)调用传递来的图形对象中的绘制函数(drawShape)绘制图形
shape.drawShape(g);
但是这样也带来了一些严重的问题,比如,在其他对象中可以访问另外一个对象的数据。
shape.x = shape.y = 100;
panel.shape = shape;
这就好比一个人的私隐(属性)可以由其他人任意获得和改变,这明显和显示世界中有所冲突。就像一个对象的性别可以由其他对象任意地改变,这是不可想象的。