在上一节,我们学习了如何使用swing和awt工具创建一个空的窗口,本节学习如何绘制简单图形。

基本绘图介绍

Java中绘制基本图形,可以使用Java类库中的Graphics类,此类位于java.awt包中。在我们自己的java程序文件中,要使用Graphics类就需要使用import java.awt.Graphics语句将Graphics类导入进来。

Graphics类提供基本的几何图形绘制方法,主要有:画线段、画矩形、画圆、画带颜色的图形、画椭圆、画圆弧、画多边形等。本项目仅用到画直线的功能,其它图形绘制请自行点击查阅Java API

Graphics类的drawLine()方法:drawLine(int x1,int y1,int x2,int y2)

此方法的功能是:在此图形上下文的坐标系中,使用当前颜色在点 (x1,y1) 和 (x2,y2)之间画一条线。

这里需要理解几个概念:

1)图形上下文:通俗点讲,就是画图环境。每个窗口构件(如主窗口、按钮等),都有一个自己的图形上下文对象,我们就是使用这个对象来实现在构件上画图。这个对象就是Graphics对象。

2)如何获得图形上下文:我们要在哪个构件上绘图,就调用那个构件的getGraphics()方法即可获得该构件的图形上下文对象,然后使用这个对象绘图。

3)Java坐标系:

Java的坐标原点(0,0)位于屏幕的左上角,坐标度量以象素为单位,水平向右为X轴的正方向,竖直向下为Y轴的正方向,每个坐标点的值表示屏幕上的一个像素点的位置,所有坐标点的值都取整数,如下图所示。
4)当前颜色:指图形上下文当前的颜色。每个图形上下文都有自己当前的颜色。通过Graphics对象的getColor()方法可获取改颜色,setColor()方法可设置颜色。

实践训练:绘制游戏区域

第一步:给DrawSee类添加成员变量,用来描述游戏区域的特征。
对DrawSee类来说,此类主要完成的功能是与用户交互,即显示游戏区域,显示数字,响应用户鼠标点击,显示用户鼠标点击后的结果等。我们现在考虑绘制10行10列游戏区域的问题。先给DrawSee类添加如下四个成员变量:
DrawSee.java文件
import java.awt.Color;
import java.awt.Container;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent; import javax.swing.JFrame; public class DrawSee extends JFrame {
private static final int sx = 50;//游戏区域10*10方块的起始横坐标
private static final int sy = 50;//游戏区域10*10方块的起始纵坐标
private static final int w = 40;//每个小方格的边长
private static final int rw = 400;//游戏区域10*10方块的边长
...
}

之所以把这些成员作为DrawSee类的成员变量,而没有作为某个成员方法的局部变量,这是因为这几个变量所描述的是DrawSee这个窗口的特征,把他们作为类成员变量更符合逻辑。但是,这几个变量只在下面第二步描述的方法中用过,其它方法中并没有使用,所以即使你将这介个变量定义在paintComponent()方法里面,也不会出现错误,程序仍能得到正确结果。

第二步:添加绘制游戏区域的方法(即绘制10行10列的红色网格)
DrawSee.java文件
     public void paintComponents(Graphics g) {
try { // 设置线条颜色为红色
g.setColor(Color.RED); // 绘制外层矩形框
g.drawRect(sx, sy, rw, rw); /* 绘制水平10个,垂直10个方格。
* 即水平方向9条线,垂直方向9条线,
* 外围四周4条线已经画过了,不需要再画。
* 同时内部64个方格填写数字。
*/
for(int i = 1; i < 10; i ++) {
// 绘制第i条竖直线
g.drawLine(sx + (i * w), sy, sx + (i * w), sy + rw); // 绘制第i条水平线
g.drawLine(sx, sy + (i * w), sx + rw, sy + (i * w)); }
} catch (Exception e) {
e.printStackTrace();
}
}

为简单起见,我们在DrawSee类的构造方法中直接调用 paintComponents方法,让其绘制10行10列的游戏网格。(重载paint方法,在其中绘制才是合理的选择)这里直接调用paintComponents会看不到绘图结果,需要在调用paintComponents之前插入一段代码,让进程等待500毫秒。代码见第48至61行:

DrawSee.java文件

 import java.awt.Color;
import java.awt.Container;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent; import javax.swing.JFrame; /**
*
* 程序入口
*
*/
public class TestDrawLine {
public static void main(String[] args) {
new DrawSee();
}
} class DrawSee extends JFrame { private static final int sx = ;//小方格宽度
private static final int sy = ;//小方格高度
private static final int w = ;
private static final int rw = ; private Graphics jg; private Color rectColor = new Color(0xf5f5f5); /**
* DrawSee构造方法
*/
public DrawSee() {
Container p = getContentPane();
setBounds(, , , );
setVisible(true);
p.setBackground(rectColor);
setLayout(null);
setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); try { Thread.sleep();
} catch (Exception e) {
e.printStackTrace();
} // 获取专门用于在窗口界面上绘图的对象
jg = this.getGraphics(); // 绘制游戏区域
paintComponents(jg); } public void paintComponents(Graphics g) {
try { // 设置线条颜色为红色
g.setColor(Color.RED); // 绘制外层矩形框
g.drawRect(sx, sy, rw, rw); /* 绘制水平10个,垂直10个方格。
* 即水平方向9条线,垂直方向9条线,
* 外围四周4条线已经画过了,不需要再画。
* 同时内部64个方格填写数字。
*/
for(int i = ; i < ; i ++) {
// 绘制第i条竖直线
g.drawLine(sx + (i * w), sy, sx + (i * w), sy + rw); // 绘制第i条水平线
g.drawLine(sx, sy + (i * w), sx + rw, sy + (i * w)); // 填写第i行从第1个方格到第8个方格里面的数字(方格序号从0开始)
for(int j = ; j < ; j ++) {
//drawString(g, j, i);
}
}
} catch (Exception e) {
e.printStackTrace();
}
} }

现在运行程序,可以看到已经绘制出10行10列的区域了。

注意,在窗口元素上绘制直线、写文字等操作,使用到的是一个叫做Graphics的对象。在构造函数的第58行语句中,this.getGraphics()语句是获取游戏窗口的绘图对象(一个Graphics对象),这里的this是指程序运行后用户看到的那个窗口,getGraphics()方法就是得到绘图对象。获取到这个对象后,被保存到成员变量jg中,这样,在其他成员方法中就可以直接使用这个jg对象来绘图了。

DrawSee类另外几个成员:

setGrid(int cx,int cy,Color color):设置被选中的cx行,cy列网格的背景

compare(int cx,int cy):比较cx行cy列网格和之前选中的网格是否可以消除

drawString(Graphics g, int x, int y):在x行y列网格上写数字

isEnd(int[][] map) :判断二维数组map是不是全0

上叙方法请读者自己分析代码,在分析时,主要抓住两个角度,一个是这个方法的逻辑过程是怎样的,第二个是方法体内用到了哪些语法知识。

下面给出DrawSee类的完整代码:

 import java.awt.Color;
import java.awt.Container;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent; import javax.swing.JFrame; /**
*
* 程序入口
*
*/
public class TestDrawLine {
public static void main(String[] args) {
new DrawSee();
}
} class DrawSee extends JFrame {
private static final long serialVersionUID = 2L;
private static final int sx = ;//小方格宽度
private static final int sy = ;//小方格高度
private static final int w = ;
private static final int rw = ;
private int px = , py = ; private Graphics jg;
private int cc = ;// 被选中的方格个数
private int[][] map;// 存放游戏数据的二维数组
private boolean isEnd = false;
private Color rectColor = new Color(0xf5f5f5); /**
* DrawSee构造方法
*/
public DrawSee() {
Container p = getContentPane();
setBounds(, , , );
setVisible(true);
p.setBackground(rectColor);
setLayout(null);
setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); try {
// 创建游戏数据地图
map = SeeAgain.createMap(); Thread.sleep();
} catch (Exception e) {
e.printStackTrace();
} // 获取专门用于在窗口界面上绘图的对象
jg = this.getGraphics(); // 绘制游戏区域
paintComponents(jg); // 添加鼠监听事件,当鼠标点击时触发
this.addMouseListener(new MouseAdapter() { // 定义鼠标点击事件响应过程
@Override
public void mouseClicked(MouseEvent e) {
// 如果游戏结束,返回,不执行后面的代码
if(isEnd) {
return;
} //获取鼠标点击的那一点的x,y坐标
int x = e.getX(), y = e.getY(); /**
* 计算当前点击的方格是第几个
* cx:当前点击的方格处于水平方向第几个
* cy: 当前点击的方格处于竖直方向第几个
*/
int cx = (x - sx) / w, cy = (y - sy) / w; /**
* 如果点击的方格处于游戏区域之外,
* 直接返回,不执行后面的代码
*/
if(cx < || cy < || cx > || cy > ) {
return;
} // 被选中的方格个数增加一个
cc ++; compare(cx,cy); }
}); } /**
* 判断二维数组map中的所有元素是否均为0,
* 只要有一个不为0,返回false,表示游戏还没结束;否则返回true表示游戏结束
* @param map 二维数组,元素为int类型
* @return
*/
public boolean isEnd(int[][] map) {
for(int[] ms : map) {
for(int m : ms) {
if(m != ) {
return false;
}
}
}
return true;
} public void paintComponents(Graphics g) {
try { // 设置线条颜色为红色
g.setColor(Color.RED); // 绘制外层矩形框
g.drawRect(sx, sy, rw, rw); /* 绘制水平10个,垂直10个方格。
* 即水平方向9条线,垂直方向9条线,
* 外围四周4条线已经画过了,不需要再画。
* 同时内部64个方格填写数字。
*/
for(int i = ; i < ; i ++) {
// 绘制第i条竖直线
g.drawLine(sx + (i * w), sy, sx + (i * w), sy + rw); // 绘制第i条水平线
g.drawLine(sx, sy + (i * w), sx + rw, sy + (i * w)); // 填写第i行从第1个方格到第8个方格里面的数字(方格序号从0开始)
for(int j = ; j < ; j ++) {
drawString(g, j, i);
}
}
} catch (Exception e) {
e.printStackTrace();
}
} private void drawString(Graphics g, int x, int y) {
// 为0就不显示
if(map[x][y] != ) {
g.setColor(Color.RED);// Graphics对象颜色在之前又被修改过,所以每次需要将颜色重新设置为红色
g.setFont(new Font("Arial", , ));// 设置Graphics对象字体大小
g.drawString(map[x][y] + "", sx + (y * w) + , sy + ((x + ) * w) - );// 绘制字符
}
} /***
* 讲制定小方格设置为指定背景颜色
* @param cx 方格的水平方向序号
* @param cy 方格的垂直方向序号
* @param color
*/
private void setGrid(int cx,int cy,Color color){
// 将绘图对象设置为灰色,后面会将所点击的方格背景设置为此颜色
jg.setColor(color); /**
* 将所点击的方格上绘制一个小一点的矩形,矩形背景颜色为color,
* 绘制的这个Rect会导致该方格上原有的文字被覆盖
*/
jg.fillRect(sx + (cx * w) + , sy + (cy * w) + , w - , w - ); // 将覆盖的数字重新写出来,这样就又看到红色的文字了。
drawString(jg, cy, cx);
} private void compare(int cx,int cy){
/**
* 如果cc是1,表示当前一共选中了一个方格,用px,py来记住这个方格的位置;
* 否则,表示现在选中的这个方格要与之前选中的方案比较,决定是否要删除
*/
if(cc == ) {
px = cx;
py = cy; // 将所点击的方格背景设置为灰色
setGrid(cx,cy,Color.LIGHT_GRAY);
}
else{//此时,cc肯定是大于1的,表示要比较两个方格的值是否相同
SeeAgain.removed(map, py, px, cy, cx );// 让SeeAgain类的remove方法去判断上一次所选
//的(px,py)处的方格值与本次选择的(cx,cy)处的方格值是否可以消掉 // 处理第一个方格
setGrid(cx,cy,rectColor); // 处理第二个方格
setGrid(px,py,rectColor); cc = ;//将cc的值复位
} // 判断是否结束游戏
isEnd = isEnd(map);
if(isEnd) {
jg.setColor(Color.RED);
jg.setFont(new Font("Arial", , ));
jg.drawString("Game Over!", , );
}
}
}

上述代码第65行至第99行,是添加窗口的鼠标点击事件,鼠标每次点击一下小方格,就要判断所点击的放个是否要被消掉。

至此,本项目任务绘图部分的知识点就介绍到这里。

Java入门:绘制简单图形的更多相关文章

  1. 学习笔记:HTML5 Canvas绘制简单图形

    HTML5 Canvas绘制简单图形 1.添加Canvas标签,添加id供js操作. <canvas id="mycanvas" height="700" ...

  2. CSS绘制简单图形

    究竟该用字体图标.图片图标.还是CSS画一个图标?我也不知道.各有千秋吧.本文将介绍如何用css绘制简单的图形,所有测试在chrome58.0完成,如果你不能得到正确结果请到caniuse查一查看看是 ...

  3. Windows控制台下绘制简单图形

    最近接触到一个很有意思的问题,如何在Windows控制台下画图,翻遍了C的头文件也没找到画图的函数,好吧,那就用Windows提供的API函数吧,看来想移植是没戏了.先画一个简单的图,类似心电图那种吧 ...

  4. shape-自绘制简单图形

    shape 可以绘制简单的图形,颜色等.它主要就是应用于selector 的一些状态. 本文内容参考自http://www.cnblogs.com/cyanfei/archive/2012/07/27 ...

  5. 利用 turtle库绘制简单图形

    turtle库是python的基础绘图库,这个库被介绍为一个最常用的用来介绍编程知识的方法库,其主要是用于程序设计入门,是标准库之一,利用turtle可以制作很多复杂的绘图. turtle名称含义为“ ...

  6. 在高德地图上用svg.js绘制简单图形

    这段时间做的一个项目,需要在地图上绘制简单的图形.在学习高德地图JS API的过程中,发现高德地图提供的点.线等API并不能满足我的需求,还好它开放了自定义图层CustomLayer,官方说自定义图层 ...

  7. java入门---简介&简单输出小例子&开发前准备

        Java是由Sun Microsystems公司于1995年5月推出的Java面向对象程序设计语言和Java平台的总称.由James Gosling和同事们共同研发,并在1995年正式推出.J ...

  8. Quartz 2D绘制简单图形

    在Quartz 2D中,绘图是通过图形上下文进行绘制的,以下绘制几个简单的图形 首先先创建一个QuartzView.swift文件继承自UIView,然后实现drawRect方法: import UI ...

  9. Golang 绘图基础 -绘制简单图形

    前一节讲的是 绘图到不同输出源,请看地址: http://www.cnblogs.com/ghj1976/p/3440856.html 上一节的例子效果是通过设置每一个点的的RGBA属性来实现的,这是 ...

随机推荐

  1. max number of clients reached Redis测试环境报错

    现象:测试服务是去redis循环取数据,早上发现服务挂了,手动登陆redis 无法输入命令,报错:max number of clients reached Redis

  2. Final阶段版本控制报告

    版本控制代码及文档要求 在coding.net版本控制; 公开项目,教师.专家.其他同学可以不注册源代码.在此公布git地址. 报告beta阶段2周中,项目的版本控制情况,不包括未在coding.ne ...

  3. java程序设计课程实验报告1

    北京电子科技学院(BESTI) 实     验    报     告 课程:Java程序设计   班级:1353       姓名:陈都  学号:20135328 成绩:             指导 ...

  4. fullPage全屏高度自适应

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  5. Beta Scrum Day 6 — 听说

    听说

  6. The user survey(用户调查)

    在周末,我们找了一些人来进行了一个调查,鉴于选择困难,我们只找到了几个真正的小学生,没有找到家长,其余那些都是找大学生来做调查的,我们和他们说,让他们把自己的立场看成是小学生或家长.下面是我们整理出来 ...

  7. python learning Process and Thread.py

    # 多进程 # Windows下面没有fork ,请在linux下跑下面的代码 import os print('Process (%s) start...' % os.getpid()) pid = ...

  8. beta发布的评论

    1. 组名:飞天小女警 项目名:礼物挑选小工具 评价:对于我们学生来说,选礼物小工具相对来说新颖,小组添加了前十名热门礼物的推荐.发布到服务器上了,未来也有很多选择的空间可以做成礼物挑选手机app,也 ...

  9. excel文件怎么使用php进行处理

    1.可以通过phpmyadmin导入csv文件 2.也可以直接使用php 处理已经将excel另存为.csv后缀的文件, 通过php专门处理csv文件的函数 如 fgetcsv() <?php ...

  10. 七类网线 支持10gb/s的速度的计算方法

    0. 说明 我是数学白痴, 只是套了下公式... 1. 七类网线的参数: 七类线 ISO/IEC 7类/F级标准 中最新的一种双绞线,它主要为了适应万兆位以太网技术的应用和发展.但它不再是一种非屏蔽双 ...