仓库:Java图形化界面: Java图形化界面学习demo与资料 (gitee.com)
很多程序如各种小游戏都需要在窗口中绘制各种图形,除此之外,即使在开发JavaEE项目时, 有 时候也必须"动态"地向客户 端生成各种图形、图表,比如 图形验证码、统计图等,这都需要利用AWT的绘图功能。
之前我们已经学习过很多组件,例如Button、Frame、Checkbox等等,不同的组件,展示出来的图形都不一样,其实这些组件展示出来的图形,其本质就是用AWT的绘图来完成的。
在AWT中,真正提供绘图功能的是Graphics对象,那么Component组件和Graphics对象存在什么关系,才能让Component绘制自身图形呢?在Component类中,提供了下列三个方法来完成组件图形的绘制与刷新:
paint(Graphics g):绘制组件的外观;
update(Graphics g):内部调用paint方法,刷新组件外观;
repaint():调用update方法,刷新组件外观;

一般情况下,update和paint方法是由AWT系统负责调用,如果程序要希望系统重新绘制组件,可以调用repaint方法完成。
实际生活中如果需要画图,首先我们得准备一张纸,然后在拿一支画笔,配和一些颜色,就可以在纸上画出来各种各样的图形,例如圆圈、矩形等等。

程序中绘图也一样,也需要画布,画笔,颜料等等。AWT中提供了Canvas类充当画布,提供了Graphics类来充当画笔,通过调用Graphics对象的setColor()方法可以给画笔设置颜色。
画图的步骤:
1.自定义类,继承Canvas类,重写paint(Graphics g)方法完成画图;
2.在paint方法内部,真正开始画图之前调用Graphics对象的setColor()、setFont()等方法设置画笔的颜色、字体等属性;
3.调用Graphics画笔的drawXxx()方法开始画图。
其实画图的核心就在于使用Graphics画笔在Canvas画布上画出什么颜色、什么样式的图形,所以核心在画笔上,下表中列出了Graphics类中常用的一些方法:
案例:
使用AWT绘图API,完成下图效果

演示代码:
- import java.awt.*;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import java.util.Random;
-
- public class SimpleDraw {
-
- private final String RECT_SHAPE="rect";
- private final String OVAL_SHAPE="oval";
-
- private Frame frame = new Frame("这里测试绘图");
-
- private Button drawRectBtn = new Button("绘制矩形");
- private Button drawOvalBtn = new Button("绘制椭圆");
-
- //用来保存当前用户需要绘制什么样的图形
- private String shape="";
-
- private MyCanvas drawArea = new MyCanvas();
-
-
-
-
- public void init(){
-
- //为按钮添加点击事件
- drawRectBtn.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- shape = RECT_SHAPE;
- drawArea.repaint();
- }
- });
-
- drawOvalBtn.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- shape = OVAL_SHAPE;
- drawArea.repaint();
- }
- });
-
- //定义一个Panel,装载两个按钮
- Panel p = new Panel();
- p.add(drawRectBtn);
- p.add(drawOvalBtn);
-
- //把panel添加到frame底部
- frame.add(p,BorderLayout.SOUTH);
-
- //设置画布的大小
- drawArea.setPreferredSize(new Dimension(300,200));
- //把画布添加到frame中
-
- frame.add(drawArea);
-
- frame.pack();
- frame.setVisible(true);
-
-
- }
-
- public static void main(String[] args) {
- new SimpleDraw().init();
- }
-
-
- //1.自定义类,继承Canvas类,重写paint方法
-
- private class MyCanvas extends Canvas{
- @Override
- public void paint(Graphics g) {
- Random r = new Random();
-
- if (shape.equals(RECT_SHAPE)){
- //绘制矩形
- g.setColor(Color.BLACK);
- g.drawRect(r.nextInt(200),r.nextInt(100),40,60);
- }
-
- if(shape.equals(OVAL_SHAPE)){
- //绘制椭圆
- g.setColor(Color.RED);
- g.drawOval(r.nextInt(200),r.nextInt(100),60,40);
- }
-
- }
- }
- }
Java也可用于开发一些动画。所谓动画,就是间隔一定的时间(通常小于0 . 1秒 )重新绘制新的图像,两次绘制的图像之间差异较小,肉眼看起来就成了所谓的动画 。
为了实现间隔一定的时间就重新调用组件的 repaint()方法,可以借助于 Swing 提供的Timer类,Timer类是一个定时器, 它有如下一个构造器 :Timer(int delay, ActionListener listener): 每间隔 delay 毫秒,系统自动触发 ActionListener 监听器里的事件处理器方法,在方法内部我们就可以调用组件的repaint方法,完成组件重绘。
案例2:
使用AWT画图技术及Timer定时器,完成下图中弹球小游戏。


演示代码2:
- package awt_swimg.day03;
-
- import awt_swimg.day01.Utils;
-
- import javax.swing.*;
- import java.awt.*;
- import java.awt.event.*;
-
- public class PinBall {
- //桌面宽度
- private final int TABLE_WIDTH = 300;
- //桌面高度
- private final int TABLE_HEIGHT = 400;
-
-
- //球拍的高度和宽度
- private final int RACKET_WIDTH = 60;
- private final int RACKET_HEIGHT = 20;
-
- //小球的大小
- private final int BALL_SIZE = 16;
-
- //定义小球纵向运行速度
- private int ySpeed = 10;
- //小球横向运行速度
- private int xSpeed = 5;
-
- //定义小球的初始坐标
- private int ballX = 120;
- private int ballY = 20;
-
- //定义球拍的初始坐标,x坐标会发生变化,y坐标不会发生变化
- private int RACKET_X = 120;
- private final int RACKET_Y = 340;
-
- //声明定时器
- private Timer timer;
- private JFrame frame=new JFrame("弹球游戏");
- private MyCanvas canvas=new MyCanvas();
- //定义游戏结束的标记
- private boolean isLose = false;
-
- private KeyListener event = new KeyAdapter() {
- @Override
- public void keyPressed(KeyEvent e) {
- int keyCode = e.getKeyCode();
- if (keyCode == KeyEvent.VK_LEFT) {
- if (RACKET_X > 0) {
- RACKET_X -= 10;
- }
- }
- if (keyCode == KeyEvent.VK_RIGHT) {
- if (RACKET_X < TABLE_WIDTH - RACKET_WIDTH) {
- RACKET_X += 10;
- }
- }
- }
- };
- private ActionListener timerTask=new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- if (ballX<=0||ballX>=TABLE_WIDTH-BALL_SIZE) {
- xSpeed=-xSpeed;
- }
- if (ballY<=0||ballY>=RACKET_Y-BALL_SIZE&&ballX>= RACKET_X &&ballX<= RACKET_X +RACKET_WIDTH) {
- ySpeed = -ySpeed;
- }
- if (ballY>RACKET_Y&&(ballX
RACKET_X+RACKET_WIDTH)) { - timer.stop();
- isLose=true;
- canvas.repaint();
- }
-
- ballX += xSpeed;
- ballY += ySpeed;
- canvas.repaint();
- }
- };
-
- private MenuBar menuBar=new MenuBar();
- private Menu option=new Menu("选项");
- private MenuItem reStart=new MenuItem("重新开始");
- private MenuItem exit=new MenuItem("退出");
- public void init(){
- frame.add(canvas);
- frame.setMenuBar(menuBar);
- menuBar.add(option);
- option.add(reStart);
- option.add(exit);
- exit.addActionListener(e -> System.exit(0));
- reStart.addActionListener(e -> {
- isLose=false;
- ballX = 120;
- ballY = 20;
- RACKET_X = 120;
- canvas.repaint();
- timer.start();
- });
- canvas.setPreferredSize(new Dimension(TABLE_WIDTH,TABLE_HEIGHT));
-
- canvas.addKeyListener(event);
- frame.addKeyListener(event);
- timer=new Timer(50,timerTask);
- timer.start();
-
- Utils.setJFrame(frame);
- }
-
- public static void main(String[] args) {
- new PinBall().init();
- }
- public class MyCanvas extends Canvas{
- @Override
- public void paint(Graphics g) {
- if (isLose) {
- g.setColor(Color.BLUE);
- g.setFont(new Font("Times",Font.BOLD,30));
- g.drawString("游戏结束!",80,200);
- }else{
- g.setColor(Color.red);
- g.fillOval(ballX, ballY, BALL_SIZE, BALL_SIZE);
- g.setColor(Color.green);
- g.fillRect(RACKET_X, RACKET_Y, RACKET_WIDTH, RACKET_HEIGHT);
- }
-
- }
- }
- }