在上一节,我们学习了如何使用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坐标系:

实践训练:绘制游戏区域
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16import 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()方法里面,也不会出现错误,程序仍能得到正确结果。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
271 public void paintComponents(Graphics g) { 2 try { 3 4 // 设置线条颜色为红色 5 g.setColor(Color.RED); 6 7 // 绘制外层矩形框 8 g.drawRect(sx, sy, rw, rw); 9 10 /* 绘制水平10个,垂直10个方格。 11 * 即水平方向9条线,垂直方向9条线, 12 * 外围四周4条线已经画过了,不需要再画。 13 * 同时内部64个方格填写数字。 14 */ 15 for(int i = 1; i < 10; i ++) { 16 // 绘制第i条竖直线 17 g.drawLine(sx + (i * w), sy, sx + (i * w), sy + rw); 18 19 // 绘制第i条水平线 20 g.drawLine(sx, sy + (i * w), sx + rw, sy + (i * w)); 21 22 23 } 24 } catch (Exception e) { 25 e.printStackTrace(); 26 } 27 }
为简单起见,我们在DrawSee类的构造方法中直接调用 paintComponents方法,让其绘制10行10列的游戏网格。(重载paint方法,在其中绘制才是合理的选择)这里直接调用paintComponents会看不到绘图结果,需要在调用paintComponents之前插入一段代码,让进程等待500毫秒。代码见第48至61行:
DrawSee.java文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
1001 import java.awt.Color; 2 import java.awt.Container; 3 import java.awt.Font; 4 import java.awt.Graphics; 5 import java.awt.event.MouseAdapter; 6 import java.awt.event.MouseEvent; 7 8 import javax.swing.JFrame; 9 10 11 /** 12 * 13 * 程序入口 14 * 15 */ 16 public class TestDrawLine { 17 public static void main(String[] args) { 18 new DrawSee(); 19 } 20 } 21 22 class DrawSee extends JFrame { 23 24 private static final int sx = 50;//小方格宽度 25 private static final int sy = 50;//小方格高度 26 private static final int w = 40; 27 private static final int rw = 400; 28 29 30 private Graphics jg; 31 32 33 34 private Color rectColor = new Color(0xf5f5f5); 35 36 /** 37 * DrawSee构造方法 38 */ 39 public DrawSee() { 40 Container p = getContentPane(); 41 setBounds(100, 100, 500, 500); 42 setVisible(true); 43 p.setBackground(rectColor); 44 setLayout(null); 45 setResizable(false); 46 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 47 48 try { 49 50 51 52 Thread.sleep(500); 53 } catch (Exception e) { 54 e.printStackTrace(); 55 } 56 57 // 获取专门用于在窗口界面上绘图的对象 58 jg = this.getGraphics(); 59 60 // 绘制游戏区域 61 paintComponents(jg); 62 63 64 } 65 66 67 68 public void paintComponents(Graphics g) { 69 try { 70 71 // 设置线条颜色为红色 72 g.setColor(Color.RED); 73 74 // 绘制外层矩形框 75 g.drawRect(sx, sy, rw, rw); 76 77 /* 绘制水平10个,垂直10个方格。 78 * 即水平方向9条线,垂直方向9条线, 79 * 外围四周4条线已经画过了,不需要再画。 80 * 同时内部64个方格填写数字。 81 */ 82 for(int i = 1; i < 10; i ++) { 83 // 绘制第i条竖直线 84 g.drawLine(sx + (i * w), sy, sx + (i * w), sy + rw); 85 86 // 绘制第i条水平线 87 g.drawLine(sx, sy + (i * w), sx + rw, sy + (i * w)); 88 89 // 填写第i行从第1个方格到第8个方格里面的数字(方格序号从0开始) 90 for(int j = 0; j < 10; j ++) { 91 //drawString(g, j, i); 92 } 93 } 94 } catch (Exception e) { 95 e.printStackTrace(); 96 } 97 } 98 99 100 }
现在运行程序,可以看到已经绘制出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类的完整代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
2141 import java.awt.Color; 2 import java.awt.Container; 3 import java.awt.Font; 4 import java.awt.Graphics; 5 import java.awt.event.MouseAdapter; 6 import java.awt.event.MouseEvent; 7 8 import javax.swing.JFrame; 9 10 11 /** 12 * 13 * 程序入口 14 * 15 */ 16 public class TestDrawLine { 17 public static void main(String[] args) { 18 new DrawSee(); 19 } 20 } 21 22 class DrawSee extends JFrame { 23 private static final long serialVersionUID = 2L; 24 private static final int sx = 50;//小方格宽度 25 private static final int sy = 50;//小方格高度 26 private static final int w = 40; 27 private static final int rw = 400; 28 private int px = 0, py = 0; 29 30 private Graphics jg; 31 private int cc = 0;// 被选中的方格个数 32 private int[][] map;// 存放游戏数据的二维数组 33 private boolean isEnd = false; 34 private Color rectColor = new Color(0xf5f5f5); 35 36 /** 37 * DrawSee构造方法 38 */ 39 public DrawSee() { 40 Container p = getContentPane(); 41 setBounds(100, 100, 500, 500); 42 setVisible(true); 43 p.setBackground(rectColor); 44 setLayout(null); 45 setResizable(false); 46 this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 47 48 try { 49 // 创建游戏数据地图 50 map = SeeAgain.createMap(); 51 52 Thread.sleep(500); 53 } catch (Exception e) { 54 e.printStackTrace(); 55 } 56 57 // 获取专门用于在窗口界面上绘图的对象 58 jg = this.getGraphics(); 59 60 // 绘制游戏区域 61 paintComponents(jg); 62 63 64 // 添加鼠监听事件,当鼠标点击时触发 65 this.addMouseListener(new MouseAdapter() { 66 67 // 定义鼠标点击事件响应过程 68 @Override 69 public void mouseClicked(MouseEvent e) { 70 // 如果游戏结束,返回,不执行后面的代码 71 if(isEnd) { 72 return; 73 } 74 75 //获取鼠标点击的那一点的x,y坐标 76 int x = e.getX(), y = e.getY(); 77 78 /** 79 * 计算当前点击的方格是第几个 80 * cx:当前点击的方格处于水平方向第几个 81 * cy: 当前点击的方格处于竖直方向第几个 82 */ 83 int cx = (x - sx) / w, cy = (y - sy) / w; 84 85 /** 86 * 如果点击的方格处于游戏区域之外, 87 * 直接返回,不执行后面的代码 88 */ 89 if(cx < 1 || cy < 1 || cx > 8 || cy > 8) { 90 return; 91 } 92 93 // 被选中的方格个数增加一个 94 cc ++; 95 96 compare(cx,cy); 97 98 } 99 }); 100 101 } 102 103 /** 104 * 判断二维数组map中的所有元素是否均为0, 105 * 只要有一个不为0,返回false,表示游戏还没结束;否则返回true表示游戏结束 106 * @param map 二维数组,元素为int类型 107 * @return 108 */ 109 public boolean isEnd(int[][] map) { 110 for(int[] ms : map) { 111 for(int m : ms) { 112 if(m != 0) { 113 return false; 114 } 115 } 116 } 117 return true; 118 } 119 120 121 public void paintComponents(Graphics g) { 122 try { 123 124 // 设置线条颜色为红色 125 g.setColor(Color.RED); 126 127 // 绘制外层矩形框 128 g.drawRect(sx, sy, rw, rw); 129 130 /* 绘制水平10个,垂直10个方格。 131 * 即水平方向9条线,垂直方向9条线, 132 * 外围四周4条线已经画过了,不需要再画。 133 * 同时内部64个方格填写数字。 134 */ 135 for(int i = 1; i < 10; i ++) { 136 // 绘制第i条竖直线 137 g.drawLine(sx + (i * w), sy, sx + (i * w), sy + rw); 138 139 // 绘制第i条水平线 140 g.drawLine(sx, sy + (i * w), sx + rw, sy + (i * w)); 141 142 // 填写第i行从第1个方格到第8个方格里面的数字(方格序号从0开始) 143 for(int j = 0; j < 10; j ++) { 144 drawString(g, j, i); 145 } 146 } 147 } catch (Exception e) { 148 e.printStackTrace(); 149 } 150 } 151 152 private void drawString(Graphics g, int x, int y) { 153 // 为0就不显示 154 if(map[x][y] != 0) { 155 g.setColor(Color.RED);// Graphics对象颜色在之前又被修改过,所以每次需要将颜色重新设置为红色 156 g.setFont(new Font("Arial", 0, 40));// 设置Graphics对象字体大小 157 g.drawString(map[x][y] + "", sx + (y * w) + 5, sy + ((x + 1) * w) - 5);// 绘制字符 158 } 159 } 160 161 /*** 162 * 讲制定小方格设置为指定背景颜色 163 * @param cx 方格的水平方向序号 164 * @param cy 方格的垂直方向序号 165 * @param color 166 */ 167 private void setGrid(int cx,int cy,Color color){ 168 // 将绘图对象设置为灰色,后面会将所点击的方格背景设置为此颜色 169 jg.setColor(color); 170 171 /** 172 * 将所点击的方格上绘制一个小一点的矩形,矩形背景颜色为color, 173 * 绘制的这个Rect会导致该方格上原有的文字被覆盖 174 */ 175 jg.fillRect(sx + (cx * w) + 1, sy + (cy * w) + 1, w - 2, w - 2); 176 177 // 将覆盖的数字重新写出来,这样就又看到红色的文字了。 178 drawString(jg, cy, cx); 179 } 180 181 private void compare(int cx,int cy){ 182 /** 183 * 如果cc是1,表示当前一共选中了一个方格,用px,py来记住这个方格的位置; 184 * 否则,表示现在选中的这个方格要与之前选中的方案比较,决定是否要删除 185 */ 186 if(cc == 1) { 187 px = cx; 188 py = cy; 189 190 // 将所点击的方格背景设置为灰色 191 setGrid(cx,cy,Color.LIGHT_GRAY); 192 } 193 else{//此时,cc肯定是大于1的,表示要比较两个方格的值是否相同 194 SeeAgain.removed(map, py, px, cy, cx );// 让SeeAgain类的remove方法去判断上一次所选 195 //的(px,py)处的方格值与本次选择的(cx,cy)处的方格值是否可以消掉 196 197 // 处理第一个方格 198 setGrid(cx,cy,rectColor); 199 200 // 处理第二个方格 201 setGrid(px,py,rectColor); 202 203 cc = 0;//将cc的值复位 204 } 205 206 // 判断是否结束游戏 207 isEnd = isEnd(map); 208 if(isEnd) { 209 jg.setColor(Color.RED); 210 jg.setFont(new Font("Arial", 0, 62)); 211 jg.drawString("Game Over!", 100, 220); 212 } 213 } 214 }
上述代码第65行至第99行,是添加窗口的鼠标点击事件,鼠标每次点击一下小方格,就要判断所点击的放个是否要被消掉。
至此,本项目任务绘图部分的知识点就介绍到这里。
转载于:https://www.cnblogs.com/bayes/p/5505640.html
最后
以上就是清秀热狗最近收集整理的关于Java入门:绘制简单图形的全部内容,更多相关Java入门内容请搜索靠谱客的其他文章。
发表评论 取消回复