前言
在上一版智能无人机平台基础上,本次迭代新增入侵者生产与移动、无人机雷达扫描检测、多对象共享内存管理等能力,基于 Java Swing + 多线程技术实现了更贴近实际场景的无人机监控仿真效果。
文章目录
-
- 前言
- 一、功能概述
- 二、技术栈
- 三、核心步骤拆解
- 四、关键技术点说明
-
- [1. 共享数据管理](#1. 共享数据管理)
- [2. 颜色检测实现雷达扫描](#2. 颜色检测实现雷达扫描)
- [3. 边界反弹逻辑](#3. 边界反弹逻辑)
- [4. 多线程协同](#4. 多线程协同)
- 五、完整代码
-
- [1. DroneUI类](#1. DroneUI类)
- [2. DroneThread类](#2. DroneThread类)
- [3. Drone类](#3. Drone类)
- [4. Intruder类](#4. Intruder类)
- [5. DroneListener类](#5. DroneListener类)
- 六、总结
一、功能概述
- 可视化窗体:构建 1200*1000 像素的窗体,标题为 "智能无人机平台",底部提供功能按钮区
- 无人机模块:支持动态生产无人机(随机初始位置、移动速度),无人机绘制雷达扫描范围
- 入侵者模块:支持生产入侵者对象(初始位置限定在监控区域外),入侵者具备独立的绘制、移动及血条属性
- 雷达检测:无人机可检测扫描范围内的颜色特征变化,识别入侵者
- 多线程与共享数据:通过自定义线程处理无人机 / 入侵者的绘制、移动、检测逻辑,监听器线程与绘制线程共享对象集合,保证数据一致性
- 边界反弹:无人机、入侵者在各自限定的窗体范围内移动,触碰边界后反向运动
二、技术栈
- 可视化框架:Swing(如 Graphics、Color、事件监听)
- 多线程:继承 Thread 类实现自定义绘制线程、ActionListener 事件监听线程
- 数据结构:ArrayList 存储无人机、入侵者对象,实现多线程共享数据
- 图形绘制:Graphics 类实现椭圆(无人机、入侵者、扫描范围)的绘制,Color 类支持透明色、RGB 色值配置
- 随机数:Random 类生成无人机 / 入侵者的初始位置、移动速度
三、核心步骤拆解
1:项目结构与类设计
规划 5 个核心类,职责分工如下:
DroneUI:窗体入口类,负责界面初始化、组件布局、线程启动及共享数据初始化;DroneThread:自定义绘制线程,处理无人机 / 入侵者的绘制、移动、雷达检测逻辑;Drone:无人机实体类,封装属性(位置、速度、尺寸、扫描范围)与行为(绘制、移动);Intruder:入侵者实体类,封装属性(位置、速度、尺寸、血量)与行为(绘制、移动);DroneListener:事件监听器类,处理按钮点击事件,生产无人机 / 入侵者对象
2:窗体初始化(DroneUI类)
- 初始化共享集合:创建
ArrayList<Drone>和ArrayList<Intruder>,作为监听器与绘制线程的共享数据容器 - 窗体配置:设置标题、尺寸、关闭方式、居中显示,添加底部按钮面板(生产无人机、生产入侵者)
- 线程关联:将共享集合赋值给监听器与绘制线程,注册按钮监听器,启动绘制线程
- 重写 paint 方法:保证窗体刷新逻辑
3:无人机实体实现(Drone类)
-
属性封装:定义位置(x/y)、速度(speedx/speedy)、尺寸(size)、扫描范围(scanSize)等核心属性
-
构造方法:初始化位置、状态、速度,默认配置尺寸、扫描范围等固定属性
-
绘制逻辑(drawDrone):
- 浅绿色透明椭圆:雷达扫描范围
- 灰色椭圆:无人机主体
- 绿色小椭圆:无人机状态标识
-
移动逻辑(move):判断边界,触碰后速度反向,实现反弹效果
4:入侵者实体实现(Intruder类)
- 属性封装:位置、速度、尺寸、血量(blood),血量控制是否绘制 / 移动;
- 构造方法:初始化位置、速度、尺寸,默认血量 100;
- 绘制逻辑(drawIntruder):血量≤0 时不绘制,否则绘制黑色椭圆(主体)+ 红色外框;
- 移动逻辑(move):血量≤0 时不移动,判断窗体边界,触碰后速度反向。
5:事件监听与对象生产(DroneListener类)
- 共享集合:接收 DroneUI 传递的无人机 / 入侵者集合
- 生产无人机:点击 "生产无人机" 时,随机生成初始位置、移动速度,创建 Drone 对象并加入集合
- 生产入侵者:点击 "生产入侵者" 时,保证初始位置在监控区域外(x<200 或 x>1000,y<175 或 y>775),随机生成速度,创建 Intruder 对象并加入集合
6:多线程绘制与检测(DroneThread类)
run 方法:
- 循环执行:通过
while(true)持续处理绘制、移动、检测 - 缓冲画布:创建 BufferedImage 作为缓冲层,避免直接绘制导致的界面闪烁
- 背景绘制:填充白色背景,绘制红色监控区域边框(200,175,800,600)
- 对象遍历:循环遍历无人机 / 入侵者集合,调用各自的绘制、移动方法
- 雷达检测:取首个无人机,遍历其扫描范围内的像素颜色,若像素灰度值 < 10(接近黑色,对应入侵者),输出检测提示
- 画布渲染:将缓冲画布绘制到窗体,线程休眠 1ms 保证流畅性
四、关键技术点说明
1. 共享数据管理
DroneUI 中初始化的droneList和intruderList,分别赋值给 DroneListener 和 DroneThread,实现 "生产 - 绘制" 的数据联动
2. 颜色检测实现雷达扫描
无人机扫描范围为浅绿色透明椭圆,入侵者为黑色椭圆。通过img.getRGB(i,j)获取扫描范围内每个像素的 RGB 值,计算灰度值(R+G+B)/3,若灰度值 < 10(黑色特征),判定扫描到入侵者
3. 边界反弹逻辑
- 无人机:限定在监控区域(200≤x≤1000、175≤y≤775)内移动,触碰边界后速度取反
- 入侵者:限定在整个窗体(0≤x≤1200、0≤y≤950)内移动,触碰边界后速度取反
speedx = -speedx/speedy = -speedy,实现反向运动
4. 多线程协同
- DroneThread:负责绘制、移动、检测的后台线程,不阻塞 UI 线程
- DroneListener:基于 Swing 事件线程,处理按钮点击,生产对象
- 线程通信:通过共享 ArrayList 间接通信
五、完整代码
1. DroneUI类
java
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
// 主界面类,创建无人机监控系统的图形界面
public class DroneUI extends JFrame {
// 监听器与无人机线程共享的数据结构
// 无人机列表
ArrayList<Drone> droneList = new ArrayList<>();
// 入侵者列表
ArrayList<Intruder> intruderList = new ArrayList<>();
public DroneUI() {
setTitle("智能无人机平台"); // 设置窗口标题
setSize(1200, 1000); // 设置窗口大小
setDefaultCloseOperation(EXIT_ON_CLOSE); // 关闭操作
setLocationRelativeTo(null); // 居中显示
// 创建按钮面板
JPanel btnPanel = new JPanel();
btnPanel.setBackground(Color.LIGHT_GRAY);
// 创建"生产无人机"按钮
JButton btn = new JButton("生产无人机");
btnPanel.add(btn);
// 创建"生产入侵者"按钮
JButton btn1 = new JButton("生产入侵者");
btnPanel.add(btn1);
// 将按钮面板添加到底部
add(btnPanel, BorderLayout.SOUTH);
setVisible(true); // 显示窗口
// 获取绘图对象
Graphics g = this.getGraphics();
// 创建无人机绘图线程
DroneThread dt = new DroneThread(g);
// 创建事件监听器
DroneListener droneL = new DroneListener();
// 为按钮注册事件监听器
btn.addActionListener(droneL);
btn1.addActionListener(droneL);
// 将共享数据结构分配给监听器和绘图线程
droneL.droneList = droneList; // 监听器线程访问的无人机列表
dt.droneList = droneList; // 无人机线程访问的无人机列表
droneL.intruderList = intruderList; // 监听器线程访问的入侵者列表
dt.intruderList = intruderList; // 无人机线程访问的入侵者列表
// 启动无人机绘图线程
dt.start();
}
// 绘制窗体,刷新界面
@Override
public void paint(Graphics g) {
super.paint(g);
}
public static void main(String[] args) {
// 启动程序
new DroneUI();
}
}
2. DroneThread类
java
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
// 无人机绘图线程类,负责绘制界面中的无人机和入侵者
public class DroneThread extends Thread {
// 无人机列表
ArrayList<Drone> droneList;
// 入侵者列表
ArrayList<Intruder> intruderList;
// 绘图对象
Graphics g;
// 构造函数
public DroneThread(Graphics g) {
this.g = g;
}
@Override
public void run() {
// 持续运行游戏循环
while (true) {
// 创建缓冲图像,避免屏幕闪烁
BufferedImage img = new BufferedImage(1200, 950, 2);
Graphics bg = img.getGraphics();
// 绘制白色背景
bg.setColor(Color.WHITE);
bg.fillRect(0, 0, 1200, 950);
// 绘制红色保护区边界
bg.setColor(Color.RED);
bg.drawRect(200, 175, 800, 600); // 800*600保护区
// 绘制并移动所有无人机
for (int j = 0; j < droneList.size(); j++) {
Drone drone = droneList.get(j);
drone.drawDrone(bg); // 绘制无人机
drone.move(); // 移动无人机
}
// 绘制并移动所有入侵者
for (int i = 0; i < intruderList.size(); i++) {
Intruder intruder = intruderList.get(i);
intruder.drawIntruder(bg); // 绘制入侵者
intruder.move(); // 移动入侵者
}
// 雷达扫描功能:检测无人机周围是否有入侵者
if(droneList.size()>0) {
System.out.println("进入检测");
Drone drone = droneList.get(0);
// 扫描无人机周围的区域
for (int i = drone.x; i < drone.x+drone.scanSize; i++) {
for (int j = drone.y; j < drone.y+drone.scanSize; j++) {
// 获取像素颜色值
int colorNum = img.getRGB(i, j);
Color c = new Color(colorNum);
// 如果平均颜色值小于10(接近黑色),认为检测到目标
if ((c.getRed() + c.getBlue() + c.getGreen()) / 3 < 10) {
System.out.println("雷达扫描到了~");
}
}
}
}
// 将缓冲图像绘制到屏幕上
g.drawImage(img, 0, 0, null);
// 延迟1毫秒,控制动画速度
try {
Thread.sleep(1);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
3. Drone类
java
import java.awt.*;
// 无人机类,定义无人机的位置、外观和行为
public class Drone {
// 属性
int x, y, speedx, speedy, size; // 位置坐标、X轴速度、Y轴速度、显示大小
int state; // 状态标识
int stateSize; // 状态指示器大小
int scanSize; // 雷达扫描范围大小
// 构造函数
public Drone(int x, int y, int state, int speedx, int speedy) {
this.x = x;
this.y = y;
this.state = state;
this.size = 30; // 无人机主体大小
this.stateSize = 15; // 状态指示器大小
this.scanSize = 100; // 扫描范围
this.speedy = speedy;
this.speedx = speedx;
}
// 绘制无人机
public void drawDrone(Graphics bg) {
// 绘制扫描范围圆圈(半透明绿色)
Color color1 = new Color(40, 246, 61, 181);
bg.setColor(color1);
bg.fillOval(x, y, scanSize, scanSize);
// 绘制无人机主体(灰色)
Color color2 = Color.GRAY;
bg.setColor(color2);
bg.fillOval(x + 35, y + 35, size, size); // 60*60区域
// 绘制状态指示器(绿色)
Color color3 = Color.GREEN;
bg.setColor(color3);
bg.fillOval(x + 42, y + 42, stateSize, stateSize);
}
// 控制无人机移动,当碰到边界时反弹
public void move() {
// 在保护区边界内移动,超出则反转方向
if (x > 300 + 600 || x < 200) { // x > 900 或 x < 200
speedx = -speedx;
}
if (y > 175 + 500 || y < 175) { // y > 675 或 y < 175
speedy = -speedy;
}
x += speedx;
y += speedy;
}
}
4. Intruder类
java
import java.awt.*;
// 入侵者类
public class Intruder {
int x, y, speedx, speedy, size; // 位置坐标、速度、大小
int blood; // 血量
// 构造函数
public Intruder(int x, int y, int speedx, int speedy, int size) {
this.x = x;
this.y = y;
this.speedx = speedx;
this.speedy = speedy;
this.size = size;
this.blood = 100; // 初始化血量为100
}
// 绘制入侵者
public void drawIntruder(Graphics g) {
// 如果血量小于等于0,则不绘制
if (blood <= 0) {
return;
}
// 黑色圆形代表入侵者主体
g.setColor(Color.BLACK);
g.fillOval(x, y, size, size);
// 红色边框
g.setColor(Color.RED);
g.drawOval(x - 1, y - 1, size + 2, size + 2);
}
// 控制入侵者移动,碰到边界时反弹
public void move() {
// 如果血量小于等于0,则停止移动
if (blood <= 0) {
return;
}
// 边界检测
if (x > 1200-size || x < 0) { // 右边界或左边界
speedx = -speedx;
}
if (y > 950-size || y < 0) { // 下边界或上边界
speedy = -speedy;
}
x += speedx;
y += speedy;
}
}
5. DroneListener类
java
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Random;
// 按钮事件监听器,处理"生产无人机"和"生产入侵者"按钮点击事件
public class DroneListener implements ActionListener {
// 共享数据结构
// 无人机列表,供监听器和绘图线程共享
ArrayList<Drone> droneList;
// 入侵者列表,供监听器和绘图线程共享
ArrayList<Intruder> intruderList;
// 生成随机数
Random random = new Random();
@Override
public void actionPerformed(ActionEvent e) {
// 获取按钮命令字符串
String ac = e.getActionCommand();
if (ac.equals("生产无人机")) {
// 在保护区内随机生成无人机位置
int x = random.nextInt(700) + 200; // x坐标范围: 200-900
int y = random.nextInt(500) + 175; // y坐标范围: 175-675
// 随机生成速度 (-2 ~ 2)
int speedx = random.nextInt(5) - 2;
int speedy = random.nextInt(5) - 2;
// 创建新无人机并添加到列表
Drone drone = new Drone(x, y, 0, speedx, speedy);
droneList.add(drone);
} else if (ac.equals("生产入侵者")) {
// 在整个界面范围内随机生成入侵者位置
int x = random.nextInt(1150); // x坐标范围: 0-1149
int y = random.nextInt(905); // y坐标范围: 0-904
// 确保入侵者不会在保护区内生成
while (true) {
// 如果位置不在保护区内,则跳出循环
if (x < 200 || x > 1000 || y < 175 || y > 775) {
break;
}
// 如果在保护区内,则重新生成位置
x = random.nextInt(1150);
y = random.nextInt(900);
}
// 随机生成速度 (-2 ~ 2)
int speedx = random.nextInt(5) - 2;
int speedy = random.nextInt(5) - 2;
// 创建新入侵者并添加到列表
Intruder itd = new Intruder(x, y, speedx, speedy, 45);
intruderList.add(itd);
}
}
}
六、总结
该版本采用 "实体类 + 控制类 + UI 类" 的分层思路,便于扩展(如新增无人机状态、入侵者攻击逻辑等),通过共享集合实现数据同步,缓冲绘制优化界面体验,雷达检测模拟真实监控场景。