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

java 图形化小工具Abstract Window Toolit :画笔Graphics,画布Canvas(),弹球小游戏的更多相关文章

  1. java 图形化小工具Abstract Window Toolit 画笔 处理位图

    具体编程来处理位图 知识点: 实现逻辑: 画板上的图片 new BufferedImage(canvasWidth,canvasHeight,BufferedImage.TYPE_INT_BGR); ...

  2. java 图形化小工具Abstract Window Toolit

      老掉牙的历史 Java1.0在发布的时候,就为我们提供了GUI操作的库,这个库系统在所有的平台下都可以运行,这套基本的类库被称作抽象窗口工具集(Abstract Window Toolit),简称 ...

  3. java 图形化小工具Abstract Window Toolit 事件处理

    事件处理设计到了三个对象: EventSource(事件源):事件发生的场所,通常就是各个组件,例如按钮.窗口,菜单等. Event (事件封装了GUI组件上发生的特定事情(通常就是一次用户操作).如 ...

  4. java 图形化小工具Abstract Window Toolit 常用组件:对话框Dialog FileDialog

    对话框 Dialog是Window类的子类,是1个容器类,属于特殊组件,对话框是可以独立存在的顶级窗口,因此用法与普通窗口的用法几乎完全一样.但对话框有如下两点需要注意. (1),对话框通常依赖于其他 ...

  5. java 图形化小工具Abstract Window Toolit ImageIO缩放图片,添加水印

    实现步骤: 读取图像Image src = ImageIO.read 创建目标图像BufferedImage distImage = new BufferedImage(dstWidth, dstHe ...

  6. java 图形化小工具Abstract Window Toolit 菜单项

    AWT 中的菜单由如下几个类组合而成 MenuBar: 菜单条,菜单的容器. Menu: 菜单组件,菜单项的容器,它也是Menultem的子类,所以可作为菜单项使用. PopupMenu: 上下文菜单 ...

  7. java 图形化小工具Abstract Window Toolit 常用组件

    基本组件 Button: 按钮,可接受单击操作 Canvas: 用于绘图的画布 Checkbox: 复选框组(也可变成单选框组件) CheckboxGroup: 用于将多个checkbox组件组合成一 ...

  8. java 图形化小工具Abstract Window Toolit ;布局管理器FlowLayout流式布局;BorderLayout边界布局;GridLayout网格布局;CardLayou重叠卡片布局;BoxLayout方框布局;绝对定位

    1.FlowLayout流式布局管理器: FlowLayout布局管理器中,组件像水流一样向某方向流动(排列),遇到障碍(边界)就折回,重头开始排列 .在默认情况下,FlowLayout局管理器从左向 ...

  9. 转:二十七、Java图形化界面设计——容器(JFrame)

    转:http://blog.csdn.net/liujun13579/article/details/7756729 二十七.Java图形化界面设计——容器(JFrame) 程序是为了方便用户使用的, ...

随机推荐

  1. .net core 3.1 WebAPi 使用 AutoMapper 9.0、10.0

    AutoMapper 可以很方便完成数据对象之间的转换. Dto -> Entity Entity -> ViewModel Step 1:通过 NuGet 安装 AutoMapper 的 ...

  2. 【2020五校联考NOIP #8】狗

    题面传送门 原题题号:Codeforces 883D 题意: 有 \(n\) 个位置,每个位置上要么有一条狗,要么有一根骨头,要么啥都没有. 现在你要给每个狗指定一个方向(朝左或朝右). 朝左的狗可以 ...

  3. Codeforces 1476G - Minimum Difference(带修莫队+根号平衡)

    Codeforces 题目传送门 & 洛谷题目传送门 震惊!我竟然独立切掉了这道 *3100 的题! 虽然此题难度的确虚高,感觉真实评分也就 2800~2900 罢.但感觉还是挺有成就感的( ...

  4. Codeforces 923E - Perpetual Subtraction(微积分+生成函数+推式子+二项式反演+NTT)

    Codeforces 题目传送门 & 洛谷题目传送门 神仙题 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 首先考虑最朴素的 \(dp\),设 \(dp_{z,i}\) 表示经 ...

  5. word2010在左侧显示目录结构

  6. 5.Maximum Product Subarray-Leetcode

    f(j+1)为以下标j结尾的连续子序列最大乘积值(1) 状态转移方程如何表示呢: 这里我们知道A[j]可能为正数(或0)或负数,那么当A[j]为正数,期望前j个乘积为正数,若为负数,则期望前面的为负数 ...

  7. 搭建FastDFS集群

    先插一张图(学习的时候找的)http://blog.csdn.net/u012453843/article/details/68957209?> 软件下载地址:主要是fastdfs.libfas ...

  8. ceph对象存储场景

    安装ceph-radosgw [root@ceph-node1 ~]# cd /etc/ceph # 这里要注意ceph的源,要和之前安装的ceph集群同一个版本 [root@ceph-node1 c ...

  9. Could not get a resource from the pool

    redis报错Could not get a resource from the pool情况是:1.可以连接redis2.可以keys *查看数据,但是发现key少了好多(其实原因就是大量的key过 ...

  10. Android Menu的基本用法

    使用xml定义Menu 菜单资源文件必须放在res/menu目录中.菜单资源文件必须使用<menu>标签作为根节点.除了<menu>标签外,还有另外两个标签用于设置菜单项和分组 ...