zoukankan      html  css  js  c++  java
  • java 图形化小工具Abstract Window Toolit :画笔Graphics,画布Canvas(),弹球小游戏

    画笔Graphics

    Java中提供了Graphics类,他是一个抽象的画笔,可以在Canvas组件(画布)上绘制丰富多彩的几何图和位图。
    Graphics常用的画图方法如下:
    • drawLine(): 绘制直线
    • drawString(): 绘制字符串
    • drawRect(): 绘制矩形
    • drawRoundRect(): 绘制带圆角的矩形
    • drawOval():绘制椭圆形
    • drawPolygon():绘制多边形边框
    • drawArc():绘制一段圆弧(可能是椭圆的圆弧)
    • drawPolyline():绘制折线
    • fillRect():填充一个矩形区域
    • fillRoundRect():填充一个圆角矩形区域
    • fillOval():填充椭圆形
    • fillPolygon():填充多边形边框
    • fillArc():填充一段圆弧(可能是椭圆的圆弧)
    • drawImage():绘制位图
    AWT专门提供了一个Canvas类作为绘图的画布,程序可以通过创建Canvas的子类,并重写它的paint()方法来实现绘图。
    测试代码:
    • Canvas()画布类 paint方法画图,方法中传入画笔形参
    • Canvas()画布类 setSize(250,250);方法设置画布大小
    • Canvas()画布类 repaint(); //清除后重新绘制
    • Graphics().setColor方法设置画笔颜色,画笔执行画图动作(红色值,绿色值,蓝色值) 红绿蓝三色取值范围0-255 组合起来可以组成人类可见的任何颜色
    import java.awt.*;
    import java.awt.event.*;
    import java.util.Random;
    import java.util.concurrent.atomic.AtomicReference;
    
    /**
     * @ClassName DrawSimple
     * @projectName: object1
     * @author: Zhangmingda
     * @description: XXX
     * date: 2021/5/7.
     */
    public class DrawSimple {
        public static void main(String[] args) {
            //窗口
            Frame frame = new Frame("简单画图示例");
    
            //窗口关闭按钮动作
            WindowListener closeListener = new WindowAdapter() {
                @Override
                public void windowClosing(WindowEvent e) {
                    System.out.println("窗口关闭");
                    System.exit(0);
                }
            };
            frame.addWindowListener(closeListener);
            //绘制图形形状变量
            AtomicReference<String> shape = new AtomicReference<>();
            //画布
            Canvas canvas = new Canvas(){
                Random random = new Random();
                @Override
                public void paint(Graphics g) { //g为画笔
                    System.out.println("画图中");
                    if (shape.get() != null){
                        switch (shape.get()){
                            case "rect":
                                //设置画笔颜色Color(红色值,绿色值,蓝色值) 红绿蓝三色取值范围0-255 组合起来可以组成人类可见的任何颜色
                                g.setColor(new Color(255,0,0));
                                //画矩形,x,y分别为起始位置,后面两个参数为宽,高 Random.nextInt(200) 为伪随机数
                                g.drawRect(20,20,random.nextInt(200),random.nextInt(200));
                                break;
                            case "oval":
                                //画椭圆
                                g.setColor(new Color(10,100,30));
                                g.drawOval(40,20,random.nextInt(200),random.nextInt(200));
                        }
                    }
                }
            };
            canvas.setSize(250,250);
            frame.add(canvas);
    
            //容器
            Panel panel = new Panel();
            //按钮
            Button drawRectBtn = new Button("画矩形");
            Button drawOvalBtn = new Button("画椭圆");
            //按钮绑定事件
            drawRectBtn.addActionListener(e ->{
                shape.set("rect");
                canvas.repaint(); //清除后重新绘制
            });
            drawOvalBtn.addActionListener(e ->{
                shape.set("oval");
                canvas.repaint(); //清除后重新绘制
            });
            panel.add(drawOvalBtn);
            panel.add(drawRectBtn);
            frame.add(panel,BorderLayout.SOUTH);
            //窗口自动调整大小
            frame.setLocation(400,300);
            frame.pack();
            frame.setVisible(true);
        }
    }

    开发弹球小游戏

    开发思路:动画,就是间隔一定的时间(通常小于1秒)重新绘制新的图像,两次绘制的图像之间差异较小,肉眼看起来就成了所谓的动画。这个程序我们要借助Swing包的一个Timer类。
    Timer(int delay, ActionListener listener): 每间隔delay秒,系统自动出发ActionListener监听器里的事件处理器(actionPerformed方法)
    知识点:
    • KeyListener 实现监听键盘按键 触发移动球拍
    • 画图逻辑:球到了画布的X轴左右端,向相反方向移动位置,到了Y轴顶端位置0,或者到了球拍接触区域向相反方向移动位置
    • Timer定时器,每隔毫秒级别重新画图
    • 用到的变量全部定义为类变量

     示例代码:

    import com.sun.source.tree.NewClassTree;
    
    import javax.swing.*;
    import java.awt.*;
    import java.awt.event.*;
    import java.util.Random;
    
    /**
     * @ClassName Pinball
     * @projectName: object1
     * @author: Zhangmingda
     * @description: XXX
     * date: 2021/5/7.
     */
    public class Pinball {
        //定义球拍初始位置用随机对象
        private Random random = new Random();
        /**
         * 设置画布大小:宽高
         */
        private int canvaWidth = 300;
        private int canvaHeight = 400;
        /**
         * 球拍初始参数
         */
        //拍子大小位置
        private int rectX = random.nextInt(200); //拍子所在横坐标位置,要在画布范围之内,
        private int rectY = 355; //拍子所在Y轴坐标位置小于400,和底部留一定空隙
        private int rectWidth = 60; //宽度60
        private int rectHeight = 15; //厚度
        //拍子按下按键拍子移动的像素大小(步伐)
        int pace =10;
    
        /**
         * 小球的尺寸位置初始参数
         */
        private int ballSize =15;
        private int ballX = random.nextInt(200);
        private int ballY = random.nextInt(100);
    
        /**
         * 小球运动速度值
         */
        private int ballYSpeed = 5; //Y 轴移动速度
        private double xyRate = random.nextDouble() - 0.5; //X轴相对比Y轴运动速度的比率,返回一个-0.5 ~0.5之间的数,移动方向为向左或者向右
        private int ballXSpeed = (int) (ballYSpeed * xyRate * 2); // X 轴运动的速度
    
        /**
         * 定时器Timer
         */
        private Timer timer;
    
        /**
         * 游戏是否结束
         */
        private boolean gameOver = false;
    
        /**
         * 方法
         */
        public void play(){
            /**
             * 定义窗口,设置位置和关闭动作
             */
            Frame frame = new Frame("弹球小游戏");
            frame.setLocation(400,300);
            frame.addWindowListener(new WindowAdapter() {
                @Override
                public void windowClosing(WindowEvent e) {
                    System.out.println("关闭游戏");
                    System.exit(0);
                }
            });
    
    
            /**
             * 定义画布
             */
            Canvas canvas = new Canvas(){
                @Override
                public void paint(Graphics g) {
                    //如果没有结束
                    if (!gameOver){
                        //画球
                        g.setColor(new Color(30,200,150));
                        g.fillOval(ballX,ballY,ballSize, ballSize);
                        //画下面的矩形拍子
                        g.setColor(new Color(75, 79, 194));
                        g.fillRect(rectX, rectY, rectWidth, rectHeight);
                    }else { //gameOver了
                        g.setColor(Color.RED);
                        g.setFont(new Font("Times",Font.BOLD,30)); // 设置字体格式字体
                        g.drawString("Game Over",70, 200);
                    }
                }
            };
            //设置画布大小
            canvas.setPreferredSize(new Dimension(canvaWidth,canvaHeight));
            frame.add(canvas);
            /**
             * 游戏核心逻辑:动画效果
             */
            timer = new Timer(50, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent actionEvent) {
                    /**
                     * 如果到了X轴的两端,就向反方向画图
                     */
                    if (ballX < 0 || ballX >= canvaWidth - ballSize)
                        ballXSpeed = -ballXSpeed;
                    /**
                     * 如果球接触到了球拍的X轴和Y轴区域内,或者跑到顶端(ballY 坐标小于0)就把Y轴反向移动
                     */
                    if (ballY < 0 || (ballY >= rectY - ballSize && ballY  < rectY - ballSize/2) && ballX + ballSize /2 >= rectX && ballX + ballSize /2 <= rectX + rectWidth) {
                        System.out.println("ballX:"+ ballX + "ballY:"+ ballY + "rectX:" + rectX + "rectY:" +rectY);
                        ballYSpeed = -ballYSpeed; //反向速度
                    }else if (ballY >= canvaHeight){ //如果球已经掉到画布之外或者 球拍下 就停止timer循环
                        timer.stop();
                        gameOver = true;
                    }
                    ballX += ballXSpeed;
                    ballY += ballYSpeed;
                    canvas.repaint();
                }
            });
            timer.start();
            /**
             * 窗口监听键盘
             */
            KeyListener keyListener = new KeyAdapter() { //添加键盘监听器
                @Override
                public void keyPressed(KeyEvent e) { //当键盘被按下时触发
    //                System.out.println("按下键盘");
                    int KeyCode = e.getKeyCode(); //获取按下的键盘代号
                    switch (KeyCode){
                        case KeyEvent.VK_LEFT://左键按下
                            if(rectX - pace > 0){
                                rectX -= pace;
                            }else {
                                rectX = 0;
                            }
                            break;
                        case KeyEvent.VK_RIGHT://右键按下
                            if (rectX + pace < canvaWidth - rectWidth){
                                rectX += pace;
                            }else {
                                rectX = canvaWidth -rectWidth;
                            }
                            break;
                    }
                    canvas.repaint();
                }
            };
            frame.addKeyListener(keyListener);
            /**
             * 窗口大小自动调节到最优,显示窗口
             */
            frame.pack();
            frame.setVisible(true);
        }
        public static void main(String[] args) {
            new Pinball().play();
        }
    }
  • 相关阅读:
    转 ShowSlow+Yslow页面前端性能测试环境搭建
    ORA-01843 无效的月份
    微信回复图片
    springmvc 监听器getWriter() has already been called for this response问题
    执子之手 与子偕老
    美字
    睡至三更时凡功名都成幻境 想到百年后无少长俱是古人
    oracle regexp_like介绍和例子
    Oracle中如何判断字符串是否全为数字
    ruby for in 循环中改变i的值无效
  • 原文地址:https://www.cnblogs.com/zhangmingda/p/14738111.html
Copyright © 2011-2022 走看看