java 图形化小工具Abstract Window Toolit :画笔Graphics,画布Canvas(),弹球小游戏

news2024/11/27 10:32:41

画笔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();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/474983.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

YOLOv8——CV界的XGBoost

yolov8是ultralytics公司于2023年1月开源的anchor-free的最新目标检测算法框架。 封装在ultralytics这个库中&#xff1a;https://github.com/ultralytics/ultralytics 它具有以下优点&#xff1a; 1&#xff0c;性能速度领先&#xff1a;借鉴了之前许多YOLO版本的trick&#x…

spring常用的事务传播行为

事务传播行为介绍 Spring中的7个事务传播行为: 事务行为 说明 PROPAGATION_REQUIRED 支持当前事务&#xff0c;假设当前没有事务。就新建一个事务 PROPAGATION_SUPPORTS 支持当前事务&#xff0c;假设当前没有事务&#xff0c;就以非事务方式运行 PROPAGATION_MANDATORY…

ChatGPT能胜任高级程序员吗?

与开发人员信任的其他软件开发工具不同&#xff0c;AI工具在训练、构建、托管和使用方式等方面都存在一些独特的风险。 自2022年底ChatGPT发布以来&#xff0c;互联网上便充斥着对其几乎相同比例的支持和怀疑的论调。不管你是否喜欢它&#xff0c;AI正在逐步进入你的开发组织。…

JAVA ssm客户信息管理系统idea开发mysql数据库web结构计算机java编程springMVC

一、源码特点 idea ssm客户信息管理系统是一套完善的web设计系统mysql数据库springMVC框架mybatis&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开 发。 java ssm客户信息管理系统idea开发mysql数据…

【五一创作】 SAAS-HRM系统概述与搭建环境

SAAS-HRM系统概述与搭建环境 学习目标&#xff1a; 理解SaaS的基本概念 了解SAAS-HRM的基本需求和开发方式掌握Power Designer的用例图 完成SAAS-HRM父模块及公共模块的环境搭建完成企业微服务中企业CRUD功能 初识SaaS 云服务的三种模式 IaaS&#xff08;基础设施即服务…

业务维度digest日志的记录与监控方案

需求 ​   为了满足从业务整体的维度 实现监控和链路复原&#xff0c;我们希望对于一个业务接口&#xff0c;记录一行请求日志&#xff0c;并通过某个 Unique Id&#xff08;如UserId、OrderId&#xff09;将多行日志关联起来&#xff0c;最终产出一批和业务强相关的数据&am…

软件维护(Software maintenance)的流程

软件维护(Software maintenance)是一个软件工程名词&#xff0c;是指在软件产品发布后&#xff0c;因修正错误、提升性能或其他属性而进行的软件修改。 软件维护主要根据需求变化或硬件环境的变化对应用程序进行部分或全部的修改&#xff0c;修改时应充分利用源程序。修改后要填…

2023年的深度学习入门指南(10) - 前端同学如何进行chatgpt开发

2023年的深度学习入门指南(10) - 前端同学如何进行chatgpt开发 在第二篇&#xff0c;我们使用openai的python库封装&#xff0c;搞得它有点像之前学习的PyTorch一样的库。这一节我们专门给它正下名&#xff0c;前端就是字面意义上的前端。 给gpt4写前端 下面我们写一个最土的…

【BeautifulSoup】——05全栈开发——如桃花来

目录索引 介绍&#xff1a;解析库&#xff1a; 安装&#xff1a;pip install BeautifulSoup4pip install lxml 标签选择器&#xff1a;1.string属性&#xff1a;.name属性&#xff1a;获取标签中的属性值&#xff1a; 实用——标准选择器&#xff1a;使用find_all()根据标签名查…

百城巡展 | 人大金仓4月“双向奔赴”告一段落

人间最美四月天&#xff0c;人大金仓走过上海、宁波、合肥&#xff0c;联合伙伴发布医疗、金融、信息安全、电子档案等多个关键领域的信创联合解决方案&#xff0c;共同为数字基础设施的安全和可持续发展贡献力量&#xff0c;吸引了线上线下近7000人参与。 左右滑动&#xff0c…

大数据架构(一)背景和概念

-系列目录- 大数据架构(一)背景和概念 大数据架构(二)大数据发展史 一、背景 1.岗位现状 大数据在一线互联网已经爆发了好多年&#xff0c;2015年-2020年(国内互联网爆发期)那时候的大数据开发&#xff0c;刚毕业能写Hive SQL配置个离线任务、整个帆软报表都20K起步。如果做到架…

Midjourney 创建私人画图机器人,共享账号如何设置独立绘画服务器(保姆级教程)

你是不是遇到以下问题&#xff1a; 1.Midjourney会员怎么自建绘图服务器&#xff0c;不受其他人的打扰&#xff1f; 2.Midjourney会员共享账号如何自建服务器&#xff0c;供其他人使用&#xff1f; 3.在官方服务器作图&#xff0c;频道里面的人太多了&#xff0c;自己的指令…

【五一创作】( 字符串) 409. 最长回文串 ——【Leetcode每日一题】

❓ 409. 最长回文串 难度&#xff1a;简单 给定一个包含大写字母和小写字母的字符串 s &#xff0c;返回 通过这些字母构造成的 最长的回文串 。 在构造过程中&#xff0c;请注意 区分大小写 。比如 "Aa" 不能当做一个回文字符串。 示例 1: 输入:s “abccccdd”…

时序预测 | Matlab实现SSA-GRU、GRU麻雀算法优化门控循环单元时间序列预测(含优化前后对比)

时序预测 | Matlab实现SSA-GRU、GRU麻雀算法优化门控循环单元时间序列预测(含优化前后对比) 目录 时序预测 | Matlab实现SSA-GRU、GRU麻雀算法优化门控循环单元时间序列预测(含优化前后对比)预测效果基本介绍程序设计参考资料 预测效果 基本介绍 Matlab实现SSA-GRU、GRU麻雀算法…

第十四章 移动和旋转(下)

本章节我们介绍另外两种形式的旋转&#xff0c;也对应了两个方法。首先是RotateAround方法&#xff0c;他是围绕穿过世界坐标中的 point 点的 axis轴旋转 angle 度。这个方法虽然比较晦涩难懂&#xff0c;但是我们使用一个案例&#xff0c;大家就非常明白了。我们创建一个新的“…

JDBC详解(三):使用PreparedStatement实现CRUD操作(超详解)

JDBC详解&#xff08;三&#xff09;&#xff1a;使用PreparedStatement实现CRUD操作&#xff08;超详解&#xff09; 前言一、操作和访问数据库二、使用Statement操作数据表的弊端三、PreparedStatement的使用1、PreparedStatement介绍2、PreparedStatement vs Statement3、Ja…

连接分析工具箱 | 利用CATO进行结构和功能连接重建

导读 本研究描述了一个连接分析工具箱(CATO)&#xff0c;用于基于扩散加权成像(DWI)和静息态功能磁共振成像(rs-fMRI)数据来重建大脑结构和功能连接。CATO是一个多模态软件包&#xff0c;使研究人员能够运行从MRI数据到结构和功能连接组图的端到端重建&#xff0c;定制其分析并…

牛郎织女

我写的十二星座十二人大多是奇女子&#xff0c;如双子的刘若英《若》、天秤的叶倩文《AB天秤座&#xff0c;Sally》、射手的桂纶镁《半人马座&#xff0c;桂纶镁》、水瓶的杨千嬅《可惜我是水瓶座》、双鱼的安妮伊能静《十二星座十二人之&#xff1a;双鱼&#xff0c;伊能&…

使用cube studio开发机器学习建模的pipeline

&#xff08;作者&#xff1a;陈玓玏&#xff09; Cube Studio目前包含了传统机器学习模板&#xff0c;400AI模型&#xff0c;欢迎私信了解哇&#xff01; 在使用cube studio进行模型训练或推理的过程中&#xff0c;我们有时会发现没有符合自己要求的模板&#xff0c;此时我们…

Unity 后处理(Post-Processing) -- (1)概览

在Unity中&#xff0c;后处理&#xff08;Post-Processing&#xff09;是在相机所捕捉的图像上应用一些特殊效果的过程&#xff0c;后处理会让图像视觉效果更好&#xff08;前提是做的好&#xff09;。 这些效果的范围有非常细微的颜色调整&#xff0c;也包括整体的美术风格的大…