最近写了一个程序,可以通过按键在画板上生成随机大小随机颜色的小球并且小球可以在画板上运动,实现了鼠标点击小球可以进行消除的功能,并且还实现了小球的暂停与重新运动的操作。
首先我们还是得先将窗体设置好,然后在窗体上添加鼠标事件监听器还有键盘事件监听器。
package com.hnu.yc0802BallThread; import java.awt.Graphics; import javax.swing.JFrame; public class BallFrame extends JFrame{ public static void main(String args[]){ BallFrame ba=new BallFrame(); ba.initUI(); } /** * 实现窗体的方法 */ public void initUI(){ // 设置窗体基本属性 this.setSize(700,700); this.setLocationRelativeTo(null); this.setDefaultCloseOperation(3); this.setResizable(false); // 添加键盘及鼠标监听器 Action ka=new Action(this); this.addKeyListener(ka); this.addMouseListener(ka); this.setVisible(true); } }
然后我们要定义小球类(继承Thread类),其中包括小球得基本属性,并且要确定好参数的传递方式,是用构造方法还是设置set与get方法。最后还得写run方法,其中就得写小球的运动算法。
package com.hnu.yc0802BallThread; import java.awt.Color; import java.awt.Graphics; import java.util.Random; public class Ball extends Thread{ private int x,y,movex,movey,size;//小球的起始坐标,每运动一次移动的坐标,大小 private BallFrame bf; // 这两个布尔变量都是在线程运行时进行判断使用,后面会介绍用法 Boolean haha=false; Boolean hahaha=true; Color co;//小球的颜色 public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } public int getSize() { return size; } public void setSize(int size) { this.size = size; } /** * 构造方法 * @param x小球起始横坐标 * @param y小球起始纵坐标 * @param movex 小球移动一步横坐标长度 * @param movey 小球移动一步纵坐标长度 * @param g 画笔 */ public Ball(int x, int y, int movex, int movey, BallFrame bf,Color co,int size) { super(); this.setX(x); this.setY(y); this.movex = movex; this.movey = movey; this.bf = bf; this.co=co; this.setSize(size); } public void run(){ Graphics g=bf.getGraphics(); while (hahaha){//hahaha(个人习惯用哈哈作为布尔变量,只要在我的代码中看到ha,那就代表布尔变量) //这里的布尔变量控制循环语句的执行,当我要结束线程,就要结束这个循环,改变布尔变量即可 if (haha){//这里的布尔变量控制小球的暂停,但是这只是让小球停在那里没有运动, //线程一直在执行,只是没有让线程执行后面的部分,所以说小球看起来不动,暂停了 continue; } g.setColor(bf.getBackground()); g.fillOval(getX(), getY(), getSize(), getSize()); // setX(getX() + movex); setY(getY() + movey); g.setColor(co); g.fillOval(getX(), getY(), getSize(), getSize()); try { Thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
接下来我们就要写实现事件监听的类,
package com.hnu.yc0802BallThread; import java.awt.Color; import java.awt.Graphics; import java.awt.Point; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.util.Random; public class Action implements KeyListener, MouseListener { BallFrame bf; Random rand;// 定义一个随机数变量,在小球的大小,颜色,运行速度随机时使用 PerfectQueue<Ball> pq;// 定义一个泛型队列变量,用来存储小球类型的对象 /** * 构造方法,用来传参 * * @param bf */ public Action(BallFrame bf) { super(); this.bf = bf; rand = new Random(); pq = new PerfectQueue<Ball>(); } @Override public void keyTyped(KeyEvent e) { // TODO Auto-generated method stub } public void keyPressed(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_U) {// 当按下U键 随机生成小球 Ball ball = new Ball(0, 0, rand.nextInt(10) + 1, rand.nextInt(10) + 1, bf, new Color(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256)), rand.nextInt(100) + 20); ball.start();// 启动线程,执行run方法,让小球动起来 pq.add(ball);// 每次都新建一个小球,然后将小球对象存储在队列中,在后面指定消除哪个小球时会用到 } if (e.getKeyCode() == KeyEvent.VK_I) {// 按下I键暂停小球运动 // 暂停只是让线程空循环,不绘制图形,在Ball类run方法中有详细解释 /** * 遍历队列,将所有小球的布尔变量haha(控制小球暂停,在Ball类run方法中有详细解释)变为true 暂停所有小球的运动 */ for (int i = 0; i < pq.size(); i++) { Ball ball = pq.get(i); ball.haha = true; } } if (e.getKeyCode() == KeyEvent.VK_O) {// 按下I键小球重新开始运动 // 启动是让线程不再空循环 要绘制图形 /** * 遍历队列,将所有小球的布尔变量haha(控制小球暂停,在Ball类run方法中有详细解释)变为false 暂停所有小球的运动 */ for (int i = 0; i < pq.size(); i++) { Ball ball = pq.get(i); ball.haha = false; } } } public void mouseReleased(MouseEvent e) { boolean ha = false;// 定义一个局部布尔变量,在判断鼠标点击点附近有没有小球时使用 int minpq = 0;// 存储到鼠标点击点的最小距离的点的下标 int min = 119;// 小球的大小是119,要将小球的坐标(小球就是画的内切圆,将矩形左上角的坐标定位小球的坐标)与鼠标点击点取距离,小于119才有效 // 得到鼠标释放的坐标 int Mouse_x = e.getX(); int Mouse_y = e.getY(); /** * 遍历队列,寻找鼠标点击点附近是否有符合要求的小球,有的话,取出距离鼠标点击点最近的那个 */ for (int i = 0; i < pq.size(); i++) { // 当不符合要求时,进入下一次循环 if (pq.get(i).getX() > Mouse_x || pq.get(i).getY() > Mouse_y || (Mouse_x - pq.get(i).getX()) > 119 || (Mouse_y - pq.get(i).getY()) > 119) { continue; } else { // pq.get(i).setX(800); // pq.get(i).setY(800); int a = (int) distence(Mouse_x, pq.get(i).getX(), Mouse_y, pq .get(i).getY());// 此方法为定义的计算两点距离的方法 if (a < min) { min = a; minpq = i; } ha = true;// 说明鼠标附近有符合要求的小球 } } if (ha) { pq.get(minpq).hahaha = false;// 将hahaha控制while语句循环的条件设置为false,停止此小球线程运行 Graphics g = bf.getGraphics();// 得到画笔 g.setColor(bf.getBackground());// 糊一个与背景色相同的小球覆盖上去 g.fillOval(pq.get(minpq).getX(), pq.get(minpq).getY(), pq .get(minpq).getSize(), pq.get(minpq).getSize()); pq.delete(minpq);//在队列中删除此小球 } } // 求两点之间距离的算法 public double distence(int ax, int bx, int ay, int by) { return Math.hypot(ax - bx, ay - by); } @Override public void mouseEntered(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mouseExited(MouseEvent e) { // TODO Auto-generated method stub } @Override public void keyReleased(KeyEvent e) { // TODO Auto-generated method stub } @Override public void mouseClicked(MouseEvent e) { // TODO Auto-generated method stub } @Override public void mousePressed(MouseEvent e) { // TODO Auto-generated method stub } }
最后,将泛型队列代码附上
package com.hnu.yc0802BallThread; public class PerfectQueue<E> { private Object[] array; private int size; // 构造方法 实例化数组 public PerfectQueue() { array = new Object[size]; } // 添加方法 public void add(E o) { Object array1[] = new Object[size + 1]; for (int i = 0; i < size; i++) { array1[i] = array[i]; } array1[size] = o; size++; array = array1; } public E get(int index){ if(index<0||index>=size) return null; return (E)array[index]; } // 删除方法 public E delete(int index) { if(index<0||index>=size) return null; Object[] temp=new Object[size-1]; for(int i=0;i<index;i++){ temp[i]=array[i]; } for(int i=index+1;i<size;i++){ temp[i-1]=array[i]; } Object obj=array[index]; size--; return (E)obj; } // 查找方法 public boolean find(Object obj) { for(int i=0;i<size;i++){ if(array[i]==obj){ return true; } } return false; } public int size(){ return size; } }
相关推荐
初识线程 线程是一个独立的运行单元,每个进程内部都有多个线程,每个线程都可以各自同时执行指令。每个线程都有自己独立的栈,但是与进程内的其他线程共享内存。但是对于.NET的客户端程序(Console,WPF,WinForms...
如今关于iOS多线程的文章层出不穷,但我觉得若想更好的领会各个实践者的文章,应该先仔细读读官方的相关文档,打好基础,定会有更好的效果。文章中有对官方文档的翻译,也有自己的理解,官方文档中代码片段的示例在...
本文将详细讲解如何初识通信,并以多线程服务器的构建为例,来阐述相关技术点。 首先,理解多线程的概念至关重要。多线程是指在一个进程中可以同时执行多个线程,这样可以充分利用CPU资源,提高程序的执行效率。在...
在头歌平台初识Redis的答案可以总结如下: 一、基础知识 Redis数据库数量: Redis默认有16个数据库,可以使用select命令进行切换。 数据库大小与键的查看: 使用DBSIZE命令查看当前数据库的大小(即键的数量)。 ...
使用方法与介绍,请参考系列文章——【深海王国】小学生都能做的语音模块?
9. **多线程**:了解线程的创建方式,同步机制(synchronized关键字、wait()、notify()、notifyAll()),以及线程池的使用。 10. **文件与目录操作**:学习如何在Java中创建、读取、修改和删除文件及目录。 11. **...
* 创建线程池时,初识化核心线程数和最大线程数 * 当有新的任务提交时,检查是否有空闲线程,如果有,则将任务分配给空闲线程 * 如果没有空闲线程,则检查是否已经达到最大线程数,如果没有,则创建新的线程 * 如果...
8.初识Lock与AbstractQueuedSynchronizer(AQS) 9.深入理解AbstractQueuedSynchronizer(AQS) 10.彻底理解ReentrantLock 11.深入理解读写锁ReentrantReadWriteLock 12.详解Condition的await和signal等待通知机制 13....
多线程 目录 进程 进程的了解 线程 什么是线程 线程的组成 线程的创建 线程的状态 线程的方法 线程的安全问题 1.进程 1.1.进程的了解 简单的来说进程就是运行中的程序,简称为进程。 单核CPU在任意一个时间节点上,...
1. 进程是什么 windows电脑中,打开任务管理器,可以看到电脑中执行的每一个程序,每一个程序就是一个进程。 Windows系统是一个多任务系统。 电脑可以同时执行多个程序。...线程抢占过程就类似于进
Java语言技术初识 Java,作为一种革命性的编程语言,由Sun Microsystems公司的James Gosling等人于1991年创立,并于1995年正式发布。它的核心特性是跨平台能力,这得益于Java虚拟机(JVM),使得“编写一次,到处...
【初识Java】 Java是一种广泛使用的面向对象的编程语言,由Sun Microsystems(后被Oracle公司收购)于1995年发布。它的设计目标是具备“简单性、面向对象、健壮性、安全性、可移植性、高效性、多线程和动态性”等...
本篇文章将围绕《头歌初识Redis答案》的内容进行展开,详细介绍Redis的基础知识、数据类型及操作、事务与监视机制、持久化策略以及主从同步等方面的内容。 #### 基础概念 - **内存存储**:Redis主要基于内存进行...
**Maven3之初识** Maven,一个在Java开发领域广泛应用的项目管理和综合工具,是Apache软件基金会的一个重要项目。它的核心目标是简化构建过程,通过提供一套标准的方式来管理项目的构建、报告和文档。Maven3是Maven...
### 头歌初识Redis知识点详解 #### 一、Redis基础知识概述 Redis是一种开源的、高性能的键值存储系统,以其快速的数据存取速度而著称。它支持多种数据结构,能够满足不同的应用场景需求。 - **数据库管理**: - ...