很多 GUI 程序都需要在组件上绘制图形,比如实现一个五子棋的小游戏,就需要在组件上绘制棋盘和棋子。在 java.awt 包中专门提供了一个 Graphics 类,它相当于一个抽象的画笔,其中提供了各种绘制图形的方法,使用 Graphics 类的方法就可以完成在组件上绘制图形。下表列出了 Graphics 类中常用的方法。
方法声明 | 方法描述 |
---|---|
void setColor(Color c) | 将此图形上下文的当前颜色设置为指定颜色 |
void setFont(Font t) | 将此图形上下文的字体设置为指定字体 |
void drawLine(int x1, int y1, int x2, int y2) | 以(x1, y1)和(x2 ,y2)为端点绘制一条线段 |
void drawRect(int x, int y, int width, int height) | 绘制指定矩形的边框。矩形的左边缘和右边缘分别位于 x 和 x + width。上边缘和下边缘分别位于 y 和 y + height |
void drawOval(int x, int y, int width, int height) | 绘制椭圆的边框。得到一个圆或椭圆,它**刚好能放入由 x、y、width 和 height 参数指定的矩形**中。椭圆覆盖区域的宽度为 width + 1 像素,高度为 height +1 像素 |
void fillRect(int x, int y, int witdth, int height) | 用当前颜色于填充指定的矩形。该矩形左边缘和右边缘分别位于 x 和 x + width - 1。上边缘和下边缘分别位于 y 和 y + height - 1 |
void fillOval(int x, int y, int width, int height) | 用当前颜色填充外界指定矩形框的椭圆 |
void drawString(String str, int x, int y) | 使用此图形上下文的当前字体和颜色绘制指定的文本 str。最左侧字符左下角位于(x, y)坐标 |
上表中列出了 Graphics 的常用方法,为了更好地理解和使用它们,下面对这些方法进行详细的说明。
① setColor()方法
用于指定上下文颜色,方法中接收一个 Color 类型的参数。在 AWT 中,Color 类代表颜色,其中定义了许多代表各种颜色的常量,例如 Color.RED,Color.BULE 等,这些常量都是 Color 类型的,可以直接作为参数传递给 setColor()方法。
② setFont()方法
用于指定上下文字体,方法中接收一个 Font 类型的参数。Font 类表示字体,可以使用 new 关键字创建 Font 对象。Font 的构造方法中接收 3 个参数,第一个是 String 类型,表示字体名称,如“宋体”“微软雅黑”等;第二个是参数是 int 类型,表示字体的类型,参数接收 Font 类的三个常量 Font.PLANT、Font.ITALC 和 Font.BOLD;第三个参数为 int 类型,表示字体的大小。
③ drawRect()方法和 drawOval()方法
用于绘制矩形和椭圆形的边框。
④ fillRect()方法和 fillOval()方法
用于使用当前的颜色填充绘制完成的矩形和椭圆形。
⑤ drawString()方法
用于绘制语段文本,第一个参数 str 表示绘制的文本内容,第二个和第三个参数 x、y 为绘制文本的左下角坐标。
了解了 Graphics 的方法后,接下来通过一个案例来演示如何使用 Graphics 在组件中进行绘图。在组件第一次显示时,**AWT 线程都会自动去调用组件**的 paint(Graphics g)方法,**为**该方法传入一个 Graphics 类型的**对象**用于绘制图形。因此,想要在组件中绘制图形,就需要重写它的 paint()方法。
目前大部分的网站为了防止用户在注册时重复提交表单,在注册页面都会有一个图片验证码。接下来通过重写 Panel 组件的 paint()方法,在一个 Panel 面板上绘制一张图片验证码,如下所示。
import java.awt.*;
import java.util.Random;
public class example14 {
public static void main(String[] args) {
//创建 Frame 对象
final Frame frame = new Frame("验证码");
//创建 Panel 对象
final Panel panle = new Mypanel();
frame.add(panle);
frame.setSize(200, 100);
//将 Frame 居中
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
class Mypanel extends Panel {
public void paint(Graphics g) {
int width = 160; //定义验证码图片的宽度
int height = 40; //定义验证码图片的高度
g.setColor(Color.LIGHT_GRAY); //设置上下文颜色
//填充验证码背景,LIGHT_GRAT,即看到的类似于灰色部分;从坐标(0,0)开始,覆盖到到坐标(width,height)
g.fillRect(0, 0, width, height);
g.setColor(Color.BLACK); //设置上下文颜色
//绘制边框,即窗口内黑色矩形部分,起点坐标为(0,0),覆盖到坐标(width -1,height -1),比验证码背景少一个像素
g.drawRect(0, 0, width - 1, height - 1);
//绘制干扰点,即小点点样的东西
Random r = new Random();
for (int i = 0; i < 100; i++) {
int x = r.nextInt(width) - 2;
int y = r.nextInt(height) - 2;
//绘制椭圆的边框,得到一个椭圆,使它刚好能放入由 x、y、2 和 2 指定的矩形中。两个 2 指的是椭圆覆盖区域的宽度为 2 像素,高度为 2 像素。因为椭圆面积过小,只有两个像素,所以在图中变成了一个个小方块,但放大后确实是椭圆形
g.drawOval(x, y, 2, 2);
}
g.setFont(new Font("黑体", Font.BOLD, 30)); //设置验证码字体为 30 字号的粗体黑体
g.setColor(Color.BLUE); //设置验证码颜色为蓝色
//产生随机验证码
char[] chars = ("0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM").toCharArray();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < 4; i++) {
int pos = r.nextInt(chars.length);
char c = chars[pos];
sb.append(c + "");
}
g.drawString(sb.toString(), 20, 30); //写入验证码,最左侧字符左下角位于(20, 30)坐标
}
}
运行程序,生成的窗口,如下所示。
2020/7/24 update
Question
复习时第二次研究源码,发现一个怎么也排查不出来的 bug。第一次学习时,只是粗略的把代码敲到 ecplise 然后运行,这次学习则是从头至尾钻研了一遍。发现窗体中的随机验证码出现了两次,以前学习的时候以为是第一次运行后留下的文本信息,没太在意,这次无意中想要尝试打印出 StringBuffer 里的内容,发现控制台输出了两条语句,这证明了那不是我的错觉,而是真实的出现了两次随机验证码。
既然发现了问题那就解决问题,但是问题就出现在这,我尝试了很长时间,但是毫无进展,从代码表面看没有丝毫的漏洞。
希望以后能够尽快解决吧。