【Java-GUI】05 绘图 Part1

案例:

package cn.dzz;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Main {

    static String shape = "";

    public static void main(String[] args) {
        // 创建窗体
        Frame frame = new Frame();

        // 创建所需的组件
        
        // 绘制矩形和椭圆的两个事件按钮
        Button rectangleButton = new Button("draw-rectangle");
        Button ellipsoidButton = new Button("draw-ellipsoid");

        // 逻辑判断

        // 判断图形的逻辑
        final String RECT = "RECT";
        final String OVAL = "OVAL";

        // 自定义的Canvas类
        class DemoCanvas extends Canvas {

            // paint方法在repaint()调用之后触发
            @Override
            public void paint(Graphics g) {
                // super.paint(g);
                if (shape.equals(RECT)) {
                    g.setColor(Color.BLACK);
                    g.drawRect(100,100,150,100);
                } else if (shape.equals(OVAL)){
                    g.setColor(Color.RED);
                    g.drawOval(100,100,150,100);
                }
            }
        }
        
        // 初始化画布容器对象
        Canvas canvas = new DemoCanvas();

        // 按钮的事件监听
        rectangleButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                shape = RECT;
                canvas.repaint();
            }
        });

        ellipsoidButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                shape = OVAL;
                canvas.repaint();
            }
        });

        // 组件组装
        Panel panel = new Panel();
        panel.add(rectangleButton);
        panel.add(ellipsoidButton);

        canvas.setPreferredSize(new Dimension(300, 300));
        frame.add(panel, BorderLayout.SOUTH);
        frame.add(canvas);

        // 自适应和可见
        frame.pack();
        frame.setVisible(true);
    }


}

预览效果

矩形和椭圆

弹球游戏的实现:

借助repaint方法,只要方法执行的频率超过肉眼的速度,

静态的画面就可以实现动画的效果

package cn.dzz;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class SamplePinball {

    private Frame frame = new Frame("Pinball-Game");

    // 弹跳的活动空间
    private final int TABLE_WIDTH = 300;
    private final int TABLE_HEIGHT = 400;

    // 球拍尺寸
    private final int RACKET_WIDTH = 60;
    private final int RACKET_HEIGHT = 10;

    // 弹球大小
    private final int BALL_SIZE = 15;

    // 弹球初始出现的坐标位置
    private int ball_location_x = 150;
    private int ball_location_y = 200;

    // 弹球的移动速度
    private int speedX = 5;
    private int speedY = 10;

    // 球拍的坐标
    private int racket_location_x = 120;
    private final int RACKET_INIT_LOCATION_Y = 340;

    private boolean isGameOver = false;

    // 计时器?
    private Timer flasher;

    private Canvas table = new PinballTable();

    class PinballTable extends Canvas {
        @Override
        public void paint(Graphics g) {
            // super.paint(g);

            // 游戏结束
            if(isGameOver) {
                g.setColor(Color.BLACK);
                g.setFont(new Font("times", Font.BOLD, 30));
                g.drawString("游戏结束", 75, 200);
            } else {
                // 游戏没有结束

                // 绘制球拍
                g.setColor(Color.LIGHT_GRAY);
                g.fillRect(
                        racket_location_x,
                        RACKET_INIT_LOCATION_Y,
                        RACKET_WIDTH,
                        RACKET_HEIGHT
                );

                // 绘制弹球
                g.setColor(Color.RED);
                g.fillOval(
                        ball_location_x,
                        ball_location_y,
                        BALL_SIZE,
                        BALL_SIZE
                );
            }
        }
    }
    
    public void init() {
        // 视图组装与逻辑控制

        // 实现球拍变化的控制
        KeyListener keyListener = new KeyAdapter(){
            @Override
            public void keyPressed(KeyEvent e) {
                // super.keyPressed(e);

                // 每一个按键都对应了一个按键代码数值
                int keyCode = e.getKeyCode();
                System.out.println("当前按下的按键是:" + keyCode);

                switch (keyCode) {
                    case KeyEvent.VK_LEFT :
                        if (racket_location_x > 0) {
                            racket_location_x -= 15;
                        }
                        break;
                    case KeyEvent.VK_RIGHT :
                        if (racket_location_x < (TABLE_WIDTH - RACKET_WIDTH)) {
                            racket_location_x += 15;
                        }
                        break;
                }
            }
        };
        
        // 每次刷新需要干的事情:
        ActionListener actionListener = new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {

                // 弹球碰到墙壁的反弹逻辑
                if (ball_location_x <= 0 || ball_location_x >= (TABLE_WIDTH - BALL_SIZE) ) {
                    speedX = -speedX;
                }
                if (ball_location_y <= 0 ||
                        (
                                ball_location_y > RACKET_INIT_LOCATION_Y - BALL_SIZE &&
                                        ball_location_x > racket_location_x &&
                                        ball_location_x < racket_location_x +  RACKET_WIDTH
                        )
                ) {
                    speedY = -speedY;
                }
                
                // 弹球越过了球拍的高度,游戏结束了
                if (ball_location_y > RACKET_INIT_LOCATION_Y - BALL_SIZE && (ball_location_x < racket_location_x || ball_location_x > racket_location_x + RACKET_WIDTH)
                ) {
                    flasher.stop();
                    isGameOver = true;
                }
                // 如果没有碰到墙壁则继续移动
                ball_location_x += speedX;
                ball_location_y += speedY;
                
                // 画布刷新
                table.repaint();
            }
        };

        // 弹球的控制  100毫秒(0.1秒)
        flasher = new Timer(100, actionListener);
        flasher.start();
        
        // 由顶级窗体监听这个事件
        frame.addKeyListener(keyListener);
        table.addKeyListener(keyListener);
        
        // 设置大小和装填组件
        table.setPreferredSize(new Dimension(TABLE_WIDTH, TABLE_HEIGHT));
        frame.add(table, BorderLayout.CENTER);

        frame.pack();
        frame.setVisible(true);
    }
}

差点忘了启动类:

package cn.dzz;

public class GUI {
    public static void main(String[] args) {
        new SamplePinball().init();
    }
}

  

posted @ 2021-02-06 01:10  emdzz  阅读(95)  评论(0编辑  收藏  举报