效果如下
代码如下(初始版本)
package cn.com.com;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test extends JPanel {
// 动态的绘图
public static void main(String[] args) {
// 0.设置窗体的内容
JFrame jf = new JFrame("JAVA动态图形");
// 1.设置一下窗体的宽高情况
jf.setSize(500, 500);
// 获取面板的内容
jf.getContentPane().add(new Test());
// 2.设置关闭窗体就是关闭线程
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 3.设置可见
jf.setVisible(true);
}
/*
* 集合 最大的容纳量 值
*/
private static List<Integer> list;
private static int size = 60;
private static int value = 100;
// 2.一个动态的集合
public Test() {
list = Collections.synchronizedList(new ArrayList<Integer>());
new Thread(new Runnable() {
public void run() {
// TODO Auto-generated method stub
while (true) {
// 2.1首先判断能不能添加,如果不能首先移除
if (list.size() > size) {
list.remove(0);// 移除第一个数据
}
// 2.1.1 产生一个随机数
Random r = new Random();
// 2.1.2 把数放在集合里面
System.out.println(r.nextInt(100));
list.add(r.nextInt(100));
// 2.2绘制的开始设置x,y
/*
* 在绘制动画图形时候如果没有调用repaint()方法的时候直接就是由线程调用
* 这个需要线程,不然没有效果
*/
repaint();
// 2.3延迟0.1s,不然的话页面绘制图片会显得有突兀
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}).start();
}
// 3 绘制一下
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
// 准备绘制
Graphics2D g2d = (Graphics2D) g;
// 设置绘制线条的质量
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
// 设置宽高
// 设置宽高
int x = getHeight() / size;
int y = getWidth() / value;
int len = list.size();
// 开始循环遍历数据
for (int i = 0; i < len - 1; i++) {
g2d.drawLine(x * (size - len + i), y * list.get(i), x
* (size - len + i + 1), y * list.get(i + 1));
}
}
}
代码如下(规范版本)
package cn.com.com;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
/*author:命运的信徒
* date:2019.7.18
* arm:java动态绘图的方法
*/
public class Plaint extends JPanel {
private List<Integer> values; // 存储数据的集合,线程不安全
private static final int MAX_VALUE = 200; // 最大值(限制里面的y数据)
private static final int MAX_COUNT_OF_VALUES = 50; // 集合的最大容量
public Plaint() {
//一个线程安全的集合
values = Collections.synchronizedList(new ArrayList<Integer>());
// 使用线程的目的,动态的,可以往集合里面添加和去除数据
new Thread(new Runnable() {
public void run() {
//一个随机数,准确的说是小于200的
Random rand = new Random();
try {
while (true) {
//生成的数添加集合,如果集合里面的数据多了就剔除数据
addValue(rand.nextInt(MAX_VALUE)); // 产生一个数据,并模拟接收并放到容器里.
System.out.println("线程");
//这个是一个重绘的方法,是线程安全的;可以调用paintComponent(Graphics g) 方法
repaint();
Thread.sleep(100);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
//准备绘制
Graphics2D g2d = (Graphics2D) g;
//设置绘制线条的质量
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//设置宽高
int w = getWidth();
int h = getHeight();
//设置x轴方向的单位长度;如果宽400px,设置最大的数据容量是50;那么一个数据就占据8px
int xDelta = w / MAX_COUNT_OF_VALUES;
//这个是集合的实时长度,肯定是小于或等于MAX_COUNT_OF_VALUES
int length = values.size();
//对集合里面的数据进行绘制,第一个点和第二个点要连线
for (int i = 0; i < length - 1; ++i) {
/*
* x轴的位置:xDelta * (MAX_COUNT_OF_VALUES - length + i) 如果集合的数据没有溢出来,一定是最后一个是最右边,第一个是集合的最大长度-集合当前长度+1;
* y轴的位置:normalizeValueForYAxis(values.get(i), h)
* 前一个数据和后一个数据相连接
*/
g2d.drawLine(xDelta * (MAX_COUNT_OF_VALUES - length + i), normalizeValueForYAxis(values.get(i), h),
xDelta * (MAX_COUNT_OF_VALUES - length + i + 1), normalizeValueForYAxis(values.get(i + 1), h));
}
}
/**
* 接收到的数据放入内存.
* @param value
*/
private void addValue(int value) {
// 循环的使用一个接收数据的空间.
// 最好是实现一个循环数组,而不是偷懒的使用ArrayList.
if (values.size() > MAX_COUNT_OF_VALUES) {
values.remove(0);
}
values.add(value);
}
/**
* 规一化y轴方向的值. 使得value在y轴的值为[0, height]之间.
*/
private int normalizeValueForYAxis(int value, int height) {
return (int) ((double) height / MAX_VALUE * value);
}
private static void createGuiAndShow() {
//窗体的名称
JFrame frame = new JFrame("java动态绘制图形");
//内容
frame.getContentPane().add(new Plaint());
//设置关闭窗体就是关闭整个程序
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//设置窗体的大小
frame.setSize(600, 600);
frame.setLocationRelativeTo(null);
//设置窗体可见
frame.setVisible(true);
}
public static void main(String[] args) {
createGuiAndShow();
}
}