画面板 MonitorPanel
package com.wwh.test.swing.monitor;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import javax.swing.JPanel;
/**
*
* 有XY轴的曲线图监控面板
*
*
*
* @author 313921
* @date 2015-01-28 22:11:04
*/
public class MonitorPanel extends JPanel implements MonitorPanelModelListener {
/**
* 最合适的Y轴线条高度间距
*/
private static final int bastYAxisLineHeightInterval = 26;
/**
* X轴上默认的线与线之间的像素
*/
public static final int DEFAULT_X_AXIS_LINE_INTERVAL = 70;
/**
* 默认的当前值文本宽度
*/
private static final int defaultCurrentTextWidth = 50;
/**
* 最少的Y轴线条数量
*/
private static final int minYAxisLineCount = 3;
private static final long serialVersionUID = 1L;
/**
* 图片
*/
private BufferedImage bufferImage;
/**
* 显示当前值的文本宽度
*/
private int currentTextWidth = 50;
private MonitorPanelModel dataModel;
private SimpleDateFormat dateF = new SimpleDateFormat("HH:mm");
/**
* 是否显示最后一个值
*/
private boolean displayLastValue = true;
private boolean drawEmptyGraph = true;
private Color fontColor = Color.BLACK;
/**
* 曲线区域的背景颜色
*/
private Color graphBackgroundColor = new Color(0, 100, 0);
private Graphics2D graphics;
/**
* 曲线的颜色
*/
private Color graphLineColor = new Color(250, 0, 0);
private String graphTitle = "监控面板";
private Color gridLineColor = new Color(0, 0, 0);
/**
* 图片的高度
*/
private int imgHeight;
/**
* 图片的宽度,整个组件就是一个画上去的图片
*/
private int imgWidth;
/**
* 标题字体
*/
private Font titleFont = new Font("宋体", Font.BOLD, 14);
/**
* 标题颜色
*/
private Color titleFontColor = Color.BLACK;
/**
* 标题的高度
*/
private int titleHeight = 20;
/**
* X轴上的线与线之间的像素
*/
private int xAxisLineInterval = DEFAULT_X_AXIS_LINE_INTERVAL;
/**
* X轴上的一个与像素点的比例
*/
private double xRatio;
/**
* X轴的文本高度
*/
private int XTextHeight = 20;
/**
* Y轴上一个与像素点的比例
*/
private double yRatio;
/**
* Y轴的文本宽度
*/
private int YTextWidth = 40;
public MonitorPanel() {
this(null);
}
public MonitorPanel(MonitorPanelModel model) {
if (model == null) {
model = new MonitorPanelModel();
}
setModel(model);
updateUI();
}
/**
*
* 计算X轴的比例
*
*/
private void calcXRatio() {
Long maxXCoords = dataModel.getMaxXCoords();
if (maxXCoords == null) {
return;
}
Long minXCoords = dataModel.getMinXCoords();
if (minXCoords == null) {
return;
}
// 曲线图的宽度
int graphWidth = getGraphWidth();
if (graphWidth <= 0) {
xRatio = 0;
return;
}
long xv = maxXCoords - minXCoords;
// 得到比例
xRatio = (double) graphWidth / (double) xv;
}
/**
*
* 计算Y轴比例
* 既:值与显示区域的像素的比例
*
*/
private void calcYRatio() {
Long maxYCoords = dataModel.getMaxYCoords();
if (maxYCoords == null) {
return;
}
Long minYCoords = dataModel.getMinYCoords();
if (minYCoords == null) {
return;
}
// 计算曲线图的高度
int graphHeight = getGraphHeight();
if (graphHeight <= 0) {
yRatio = 0;
return;
}
long yd = maxYCoords - minYCoords;// Y轴
if (yd <= 0) {
yRatio = 0;
return;
}
yRatio = (double) graphHeight / (double) yd;// 得到比例
}
private void clearBufferImage() {
graphics.setBackground(getBackground());
graphics.clearRect(0, 0, imgWidth, imgHeight);
}
private void drawDefaultXAxis() {
int graphWidth = getGraphWidth();
int graphHeight = getGraphHeight();
// 每隔一定的像素画一条竖线
graphics.setColor(gridLineColor);
for (int i = YTextWidth + xAxisLineInterval; i < YTextWidth + graphWidth; i += xAxisLineInterval) {
graphics.drawLine(i, titleHeight, i, titleHeight + graphHeight);
}
}
private void drawDefaultYAxis() {
// 每隔一定的像素画一条线
int graphWidth = getGraphWidth();
int graphHeight = getGraphHeight();
// 画横线
graphics.setColor(gridLineColor);
for (int i = graphHeight; i - bastYAxisLineHeightInterval > 0; i -= bastYAxisLineHeightInterval) {
int yPosition = i - bastYAxisLineHeightInterval + titleHeight;
graphics.drawLine(YTextWidth, yPosition, YTextWidth + graphWidth, yPosition);
}
}
/**
* 绘制曲线
*/
private void drawGraph() {
graphics.setColor(graphLineColor);
List coordinatelist = dataModel.getCoordinatelist();
int size = coordinatelist.size();
if (size < 2) {
return;
}
int[] xPoints = new int[size];
int[] yPoints = new int[size];
for (int i = 0; i < size; i++) {
xPoints[i] = getXPoint(coordinatelist.get(i).getxValue());
yPoints[i] = getYPoint(coordinatelist.get(i).getyValue());
}
graphics.drawPolyline(xPoints, yPoints, size);
// 画一个当前值
Font font = graphics.getFont();
FontMetrics fm = graphics.getFontMetrics(font);
int descent = fm.getDescent();
graphics.setColor(fontColor);
int _yPoint = yPoints[size - 1];
int graphWidth = getGraphWidth();
int _xPoint = YTextWidth + graphWidth + 1;
long currentValue = coordinatelist.get(coordinatelist.size() - 1).getyValue();
String valueOf = String.valueOf(currentValue);
graphics.drawString(valueOf, _xPoint, _yPoint - descent);
graphics.drawLine(_xPoint, _yPoint, _xPoint + fm.stringWidth(valueOf), _yPoint);
}
/**
*
* 画背景
*
*/
private void drawGraphBackgound() {
int graphWidth = getGraphWidth();
int graphHeight = getGraphHeight();
graphics.setColor(graphBackgroundColor);
// big.fill3DRect(YTextWidth, titleHeight, imgWidth - YTextWidth
// - cutlineWidth, imgHeight - titleHeight - XTextHeight, false);
// 填充指定的矩形。该矩形左边缘和右边缘分别位于 x 和 x + width - 1。上边缘和下边缘分别位于 y 和 y + height -
// 1。得到的矩形覆盖 width 像素宽乘以 height 像素高的区域。使用图形上下文的当前颜色填充该矩形。
graphics.fillRect(YTextWidth, titleHeight, graphWidth, graphHeight);
graphics.setColor(gridLineColor);
// 绘制指定矩形的边框。矩形的左边缘和右边缘分别位于 x 和 x + width。上边缘和下边缘分别位于 y 和 y +
// height。使用图形上下文的当前颜色绘制该矩形。
graphics.drawRect(YTextWidth, titleHeight, graphWidth, graphHeight);
}
/**
*
* 将内容画在图片上
*
*/
private void drawImage() {
int tw = getWidth();
int th = getHeight();
if (tw != imgWidth || th != imgHeight) {
// 大小有变化,重建一张图片
imgWidth = tw;
imgHeight = th;
bufferImage = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB);
graphics = bufferImage.createGraphics();
}
if (bufferImage == null) {
return;
}
// 先清空图片
clearBufferImage();
// 画标题
drawTitle();
// 画内容区域 背景
drawGraphBackgound();
// 获取XY轴上的线
long[] xLine = dataModel.getXAxisLines(getBestXAxisLineCount());
long[] yLine = dataModel.getYAxisLines(getBestYAxisLineCount());
// 计算X 和 Y 的比例
calcYRatio();
calcXRatio();
// 画X坐标
if (xLine != null) {
drawXAxis(xLine);
} else {
if (drawEmptyGraph) {
// 画缺省的X坐标
drawDefaultXAxis();
}
}
// 画Y坐标
if (yLine != null) {
drawYAxis(yLine);
} else if (drawEmptyGraph) {
// 画缺省的Y坐标
drawDefaultYAxis();
}
// 画曲线
drawGraph();
}
/**
*
* 画标题
*
*/
private void drawTitle() {
if (graphTitle == null || graphTitle.isEmpty() || titleHeight < 1) {
return;
}
graphics.setColor(titleFontColor);
graphics.setFont(titleFont);
FontMetrics fm = graphics.getFontMetrics(titleFont);
int titleWidth = fm.stringWidth(graphTitle);
int graphWidth = getGraphWidth();
int titleX = (graphWidth - titleWidth) / 2 + YTextWidth;
graphics.drawString(graphTitle, titleX, fm.getAscent());
}
/**
*
* 画X轴
*
*/
private void drawXAxis(long[] xLine) {
if (xLine == null) {
return;
}
Font font = graphics.getFont();
FontMetrics fm = graphics.getFontMetrics(font);
int ascent = fm.getAscent();
// int descent = fm.getDescent();
// int fHeight = fm.getHeight();
int graphHeight = getGraphHeight();
// 画X坐标
for (long l : xLine) {
int xPoint = getXPoint(l);
graphics.setColor(gridLineColor);
graphics.drawLine(xPoint, titleHeight, xPoint, titleHeight + graphHeight);
Date date = new Date(l);
String dateStr = dateF.format(date);
graphics.setColor(fontColor);
graphics.drawString(dateStr, xPoint, titleHeight + graphHeight + ascent);
}
}
/**
*
* 画Y轴
*
*/
private void drawYAxis(long[] yLine) {
if (yLine == null) {
return;
}
Font font = graphics.getFont();
FontMetrics fm = graphics.getFontMetrics(font);
int descent = fm.getDescent();
// 先设置字体
graphics.setFont(font);
// 画最大值
// String maxYStr = String.valueOf(maxY);
// big.drawString(maxYStr, YTextWidth - fm.stringWidth(maxYStr) - 1,
// titleHeight + descent);
// // 画最小值
// String minYStr = String.valueOf(minY);
// big.drawString(minYStr, YTextWidth - fm.stringWidth(minYStr) - 1,
// titleHeight + graphHeight);
int graphWidth = getGraphWidth();
for (long l : yLine) {
String yNumberStr = String.valueOf(l);
int yPosition = getYPoint(l);
if (YTextWidth > 0) {
// 数字
graphics.setColor(fontColor);
graphics.drawString(yNumberStr, YTextWidth - fm.stringWidth(yNumberStr) - 1, yPosition + descent);
}
// 画横线
graphics.setColor(gridLineColor);
graphics.drawLine(YTextWidth, yPosition, YTextWidth + graphWidth, yPosition);
}
}
private int getBestXAxisLineCount() {
// 在X轴能显示几条线
int lineCount = getGraphWidth() / xAxisLineInterval;
lineCount = lineCount > 1 ? lineCount : 1;
return lineCount;
}
/**
* 根据坐标系高度计算最佳的横线条数
*
* @return
*/
private int getBestYAxisLineCount() {
int lineCount = getGraphHeight() / bastYAxisLineHeightInterval;
lineCount = lineCount > minYAxisLineCount ? lineCount : minYAxisLineCount;
return lineCount;
}
public int getCurrentTextWidth() {
return currentTextWidth;
}
public boolean getDisplayLastValue() {
return displayLastValue;
}
public Color getFontColor() {
return fontColor;
}
public Color getGraphBackgroundColor() {
return graphBackgroundColor;
}
/**
* 获取曲线图区域的高度
*
* @return
*/
public int getGraphHeight() {
if (bufferImage == null) {
return 0;
}
return bufferImage.getHeight() - titleHeight - XTextHeight;
}
public Color getGraphLineColor() {
return graphLineColor;
}
public String getGraphTitle() {
return graphTitle;
}
/**
* 获取曲线图区域的宽度
*
* @return
*/
public int getGraphWidth() {
if (bufferImage == null) {
return 0;
}
return bufferImage.getWidth() - YTextWidth - currentTextWidth;
}
public Color getGridLineColor() {
return gridLineColor;
}
/**
*
* 获取值对应X点坐标
*
*
* @param value
* @return
*/
private int getXPoint(long value) {
Long minXCoords = dataModel.getMinXCoords();
long v = value - minXCoords;
int x = (int) (v * xRatio);
return x + YTextWidth;
}
/**
*
* 获取值对应Y点坐标
*
*
* @param value
* @return
*/
private int getYPoint(long value) {
Long minYCoords = dataModel.getMinYCoords();
long v = value - minYCoords;
int y = (int) (v * yRatio);
int graphHeight = getGraphHeight();
return graphHeight - y + titleHeight;
}
public boolean isDrawEmptyGraph() {
return drawEmptyGraph;
}
@Override
public void monitorPanelChanged(MonitorPanelModelEvent e) {
repaint();
}
@Override
public void paint(Graphics g) {
super.paint(g);
drawImage();
// 用图片
if (bufferImage != null) {
g.drawImage(bufferImage, 0, 0, this);
}
}
public void setCurrentTextWidth(int currentTextWidth) {
this.currentTextWidth = currentTextWidth;
}
public void setDisplayLastValue(boolean display) {
displayLastValue = display;
if (display) {
currentTextWidth = defaultCurrentTextWidth;
} else {
currentTextWidth = 0;
}
}
public void setDrawEmptyGraph(boolean drawEmptyGraph) {
this.drawEmptyGraph = drawEmptyGraph;
}
public void setFontColor(Color fontColor) {
this.fontColor = fontColor;
}
public void setGraphBackgroundColor(Color graphBackgroundColor) {
this.graphBackgroundColor = graphBackgroundColor;
}
public void setGraphLineColor(Color graphLineColor) {
this.graphLineColor = graphLineColor;
}
public void setGraphTitle(String title) {
this.graphTitle = title;
}
public void setGridLineColor(Color gridLineColor) {
this.gridLineColor = gridLineColor;
}
public void setModel(MonitorPanelModel model) {
if (model == null) {
throw new IllegalArgumentException("不能为空");
}
if (this.dataModel != model) {
MonitorPanelModel old = this.dataModel;
if (old != null) {
old.removeMonitorPanelModelListener(this);
}
this.dataModel = model;
model.addMonitorPanelModelListener(this);
repaint();
}
}
}
数据模型 MonitorPanelModel
package com.wwh.test.swing.monitor;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.event.EventListenerList;
// 应该抽象出接口
public class MonitorPanelModel implements Serializable {
public enum XAxisMode {
AUTO, FIXED, KEEP_MOVE
}
public enum YAxisMode {
AUTO, FIXED
}
/**
* 默认的最大坐标点的数量1000
*/
public static final int DEFAULT_MAX_COORDINATE_NUMBER = 1000;
private static final long serialVersionUID = 1L;
/**
* 坐标集合
*/
private List coordinatelist;
/**
* 使X轴呈现一个向左边移动的效果
* 需要指定一个时间段
*/
private Long keepMoveTimeInterval;
private EventListenerList listenerList = new EventListenerList();
/**
* 最大的坐标点个数
*/
private int maxCoordinateCount = DEFAULT_MAX_COORDINATE_NUMBER;
/**
* 最大X坐标
*/
private Long maxXCoords;
/**
* X轴上的最大值
*/
private Long maxXValue;
/**
* 最大Y坐标
*/
private Long maxYCoords;
/**
* Y轴上的最大值
*/
private Long maxYValue;
/**
* 最小X坐标
*/
private Long minXCoords;
/**
* X轴上的最小值
*/
private Long minXValue;
/**
* 最小Y坐标
*/
private Long minYCoords;
/**
* Y轴上的最小值
*/
private Long minYValue;
/**
* 记录一个开始的时间
*/
private Long startTime;
/**
* X 轴间距
*/
private Long xAxisInterval;
private XAxisMode xAxisMode = XAxisMode.AUTO;
/**
* Y轴间距
*/
private Long yAxisInterval;
private YAxisMode yAxisMode = YAxisMode.AUTO;
public MonitorPanelModel() {
coordinatelist = new ArrayList();
}
public void addCoordinate(Coordinate coordinate) {
coordinatelist.add(coordinate);
if (coordinatelist.size() > maxCoordinateCount) {
coordinatelist.remove(0);
fireMonitorPanelDataChanged();
} else {
fireMonitorPanelDataAdd(coordinate);
}
}
public void addMonitorPanelModelListener(MonitorPanelModelListener l) {
listenerList.add(MonitorPanelModelListener.class, l);
}
/**
* 根据间隔计算Y轴上的线条数量
*
* @param interval
* @return
*/
private int calcLineCountByInterval(long interval) {
// 计算Y轴的最大值
long tmp = maxYValue / interval;
maxYCoords = tmp * interval;
if (maxYCoords < maxYValue) {
maxYCoords += interval;
}
tmp = minYValue / interval;
minYCoords = tmp * interval;
if (minYCoords > minYValue) {
minYCoords -= interval;
}
long line = (maxYCoords - minYCoords) / interval;
yAxisInterval = interval;
return (int) line;
}
public void clearCoordinate() {
coordinatelist.clear();
fireMonitorPanelDataChanged();
}
private void fireMonitorPanelChanged(MonitorPanelModelEvent e) {
Object[] listeners = listenerList.getListenerList();
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners[i] == MonitorPanelModelListener.class) {
((MonitorPanelModelListener) listeners[i + 1]).monitorPanelChanged(e);
}
}
}
private void fireMonitorPanelDataAdd(Coordinate coordinate) {
refreshValue(coordinate);
fireMonitorPanelChanged(new MonitorPanelModelEvent(this));
}
private void fireMonitorPanelDataChanged() {
// 刷新数据
refreshAllValue();
fireMonitorPanelChanged(new MonitorPanelModelEvent(this));
}
private void fireMonitorPanelPropertyChanged(String property, Object oldValue, Object newValue) {
// 属性先不管
fireMonitorPanelChanged(new MonitorPanelModelEvent(this));
}
private long[] getAutoXAxisLines(int bestXLineCount) {
if (maxXValue == null || minXValue == null) {
return null;
}
long differ = maxXValue - minXValue;
if (differ == 0) {
return null;
}
minXCoords = minXValue;
maxXCoords = maxXValue;
xAxisInterval = differ / bestXLineCount;
if (xAxisInterval < 1) {
return null;
}
List l = new ArrayList<>();
long tmp = maxXCoords;
while (tmp > minXCoords) {
l.add(tmp);
tmp -= xAxisInterval;
}
long[] ret = new long[l.size()];
for (int i = 0; i < ret.length; i++) {
ret[i] = l.get(i);
}
return ret;
}
private long[] getAutoYAxisLines(int bestYLineCount) {
if (maxYValue == null || minYValue == null) {
return null;
}
long differValue = maxYValue - minYValue;
if (differValue == 0) {
// 此时可能是一条横线
yAxisInterval = 1L;
long absMaxYValue = Math.abs(maxYValue);
if (absMaxYValue > 10) {
double log = Math.log10(absMaxYValue / 10);
// 四舍五入取整
log = Math.round(log);
// 间距
yAxisInterval = (long) Math.pow(10, log);
}
maxYCoords = ((maxYValue / yAxisInterval) + 1) * yAxisInterval;
minYCoords = ((maxYValue / yAxisInterval) - 1) * yAxisInterval;
long middleValue = (maxYValue / yAxisInterval) * yAxisInterval;
return new long[] { minYCoords, middleValue, maxYCoords };
}
long interval = 1;
if (differValue > 10) {
double log = Math.log10(differValue / 10);
// 四舍五入取整
log = Math.round(log);
// 间距
interval = (long) Math.pow(10, log);
}
readjustYAxis(interval, bestYLineCount);
// 返回Y轴上的坐标线
return getFixedYAxisLines();
}
public List getCoordinatelist() {
return Collections.unmodifiableList(coordinatelist);
}
public int getCoordinateSize() {
return coordinatelist.size();
}
private long[] getFixedXAxisLines() {
if (maxXCoords == null || minXCoords == null || xAxisInterval == null) {
throw new IllegalArgumentException("固定模式下,最大值、最小值、间距都不能为空");
}
List l = new ArrayList<>();
long tmp = minXCoords;
while (tmp <= maxXCoords) {
l.add(tmp);
tmp += xAxisInterval;
}
long[] ret = new long[l.size()];
for (int i = 0; i < ret.length; i++) {
ret[i] = l.get(i);
}
return ret;
}
private long[] getFixedYAxisLines() {
if (maxYCoords == null || minYCoords == null || yAxisInterval == null) {
throw new IllegalArgumentException("固定模式下,最大值、最小值、间距都不能为空");
}
List l = new ArrayList<>();
long tmp = minYCoords;
while (tmp <= maxYCoords) {
l.add(tmp);
tmp += yAxisInterval;
}
long[] ret = new long[l.size()];
for (int i = 0; i < ret.length; i++) {
ret[i] = l.get(i);
}
return ret;
}
public Long getKeepMoveTimeInterval() {
return keepMoveTimeInterval;
}
private long[] getKeepMoveXAxisLines(int bestXLineCount) {
if (keepMoveTimeInterval == null || keepMoveTimeInterval < 1) {
throw new IllegalArgumentException("移动模式下,固定的时间段不能为空或小于1");
}
if (startTime == null) {
startTime = System.currentTimeMillis();
}
maxXCoords = System.currentTimeMillis();
minXCoords = maxXCoords - keepMoveTimeInterval;
xAxisInterval = keepMoveTimeInterval / bestXLineCount;
if (xAxisInterval < 1) {
return null;
}
List l = new ArrayList<>();
long tmp = startTime;
while (tmp <= maxXCoords) {
if (tmp >= minXCoords) {
l.add(tmp);
}
tmp += xAxisInterval;
}
long[] ret = new long[l.size()];
for (int i = 0; i < ret.length; i++) {
ret[i] = l.get(i);
}
return ret;
}
public int getMaxCoordinateCount() {
return maxCoordinateCount;
}
public Long getMaxXCoords() {
return maxXCoords;
}
public Long getMaxXValue() {
return maxXValue;
}
public Long getMaxYCoords() {
return maxYCoords;
}
public Long getMaxYValue() {
return maxYValue;
}
public Long getMinXCoords() {
return minXCoords;
}
public Long getMinXValue() {
return minXValue;
}
public Long getMinYCoords() {
return minYCoords;
}
public Long getMinYValue() {
return minYValue;
}
public MonitorPanelModelListener[] getMonitorPanelModelListeners() {
return listenerList.getListeners(MonitorPanelModelListener.class);
}
public long getXAxisFirstValue() {
if (coordinatelist.isEmpty()) {
return 0;
}
return coordinatelist.get(0).getxValue();
}
public Long getxAxisInterval() {
return xAxisInterval;
}
public long getXAxisLastValue() {
if (coordinatelist.isEmpty()) {
return 0;
}
return coordinatelist.get(coordinatelist.size() - 1).getxValue();
}
/**
* X 轴上要画的竖线
*
* @param bestXLineCount 最佳的竖线条数
* @return
*/
public long[] getXAxisLines(int bestXLineCount) {
switch (xAxisMode) {
case AUTO:
return getAutoXAxisLines(bestXLineCount);
case FIXED:
return getFixedXAxisLines();
case KEEP_MOVE:
return getKeepMoveXAxisLines(bestXLineCount);
default:
return null;
}
}
public XAxisMode getxAxisMode() {
return xAxisMode;
}
public Long getyAxisInterval() {
return yAxisInterval;
}
/**
* Y 轴上要画的横线
*
* @param bestYLineCount 最佳的横线条数
* @return
*/
public long[] getYAxisLines(int bestYLineCount) {
switch (yAxisMode) {
case AUTO:
return getAutoYAxisLines(bestYLineCount);
case FIXED:
return getFixedYAxisLines();
default:
return null;
}
}
public YAxisMode getyAxisMode() {
return yAxisMode;
}
/**
* 重新计算Y轴
*
* @param interval
*/
private void readjustYAxis(long interval, int bestYLineCount) {
// 先根据目前的间距计算一次Y轴的行数
int lineCount = calcLineCountByInterval(interval);
// 再尝试调整为最佳的
long newInterval = 0;
if (bestYLineCount > lineCount) {
// 减小间距
float f = (float) bestYLineCount / lineCount;
int p = Math.round(f);
if (p == 1) {
return;
} else {
for (int i = p; i > 1; i--) {
if (interval % i == 0) {
newInterval = interval / i;
break;
}
}
}
} else {
// 增加间距
float f = (float) lineCount / bestYLineCount;
int p = Math.round(f);
if (p == 1) {
return;
} else {
newInterval = interval * p;
}
}
if (newInterval != 0) {
// 根据调整后的间距再算一次
lineCount = calcLineCountByInterval(newInterval);
}
}
private void refreshAllValue() {
minXValue = null;
maxXValue = null;
minYValue = null;
maxYValue = null;
for (Coordinate coordinate : coordinatelist) {
refreshValue(coordinate);
}
}
private void refreshValue(Coordinate coordinate) {
long y = coordinate.getyValue();
long x = coordinate.getxValue();
if (maxYValue == null || y > maxYValue) {
maxYValue = y;
}
if (minYValue == null || y < minYValue) {
minYValue = y;
}
if (maxXValue == null || x > maxXValue) {
maxXValue = x;
}
if (minXValue == null || x < minXValue) {
minXValue = x;
}
}
public void removeMonitorPanelModelListener(MonitorPanelModelListener l) {
listenerList.remove(MonitorPanelModelListener.class, l);
}
public void setCoordinatelist(List coordinatelist) {
if (coordinatelist == null) {
throw new IllegalArgumentException("不能为空");
}
this.coordinatelist = coordinatelist;
fireMonitorPanelDataChanged();
}
public void setKeepMoveTimeInterval(Long keepMoveTimeInterval) {
fireMonitorPanelPropertyChanged(null, null, null);
this.keepMoveTimeInterval = keepMoveTimeInterval;
}
public void setMaxCoordinateCount(int maxCoordinateCount) {
fireMonitorPanelPropertyChanged(null, null, null);
this.maxCoordinateCount = maxCoordinateCount;
}
public void setMaxXCoords(Long maxXCoords) {
fireMonitorPanelPropertyChanged(null, null, null);
this.maxXCoords = maxXCoords;
}
public void setMaxYCoords(Long maxYCoords) {
fireMonitorPanelPropertyChanged(null, null, null);
this.maxYCoords = maxYCoords;
}
public void setMinXCoords(Long minXCoords) {
fireMonitorPanelPropertyChanged(null, null, null);
this.minXCoords = minXCoords;
}
public void setMinYCoords(Long minYCoords) {
fireMonitorPanelPropertyChanged(null, null, null);
this.minYCoords = minYCoords;
}
public void setxAxisInterval(Long xAxisInterval) {
fireMonitorPanelPropertyChanged(null, null, null);
this.xAxisInterval = xAxisInterval;
}
public void setxAxisMode(XAxisMode xAxisMode) {
fireMonitorPanelPropertyChanged(null, null, null);
this.xAxisMode = xAxisMode;
}
public void setyAxisInterval(Long yAxisInterval) {
fireMonitorPanelPropertyChanged(null, null, null);
this.yAxisInterval = yAxisInterval;
}
public void setyAxisMode(YAxisMode yAxisMode) {
fireMonitorPanelPropertyChanged(null, null, null);
this.yAxisMode = yAxisMode;
}
}
坐标 Coordinate
package com.wwh.test.swing.monitor;
/**
*
* xy坐标
* X轴 为 具体的值
* Y轴 为 时间
*
*
* @author wwh
*/
public class Coordinate {
private long xValue;
private long yValue;
public Coordinate(long x, long y) {
this.xValue = x;
this.yValue = y;
}
public long getxValue() {
return xValue;
}
public void setxValue(long xValue) {
this.xValue = xValue;
}
public long getyValue() {
return yValue;
}
public void setyValue(long yValue) {
this.yValue = yValue;
}
}
事件 MonitorPanelModelEvent
package com.wwh.test.swing.monitor;
public class MonitorPanelModelEvent extends java.util.EventObject {
private static final long serialVersionUID = 1L;
public MonitorPanelModelEvent(Object source) {
super(source);
}
}
监听器接口 MonitorPanelModelListener
package com.wwh.test.swing.monitor;
public interface MonitorPanelModelListener extends java.util.EventListener {
public void monitorPanelChanged(MonitorPanelModelEvent e);
}
测试 MonitorPanelTest
package com.wwh.test.swing.monitor;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import com.wwh.test.swing.monitor.MonitorPanelModel.XAxisMode;
import com.wwh.test.swing.monitor.MonitorPanelModel.YAxisMode;
public class MonitorPanelTest extends JFrame {
private static final long serialVersionUID = 1L;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MonitorPanelTest frame = new MonitorPanelTest();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private JButton btn_clear1;
private JButton btn_clear2;
private JButton btn_clear3;
private JButton btn_clear4;
private JButton btn_start2;
private JButton btn_start3;
private JButton btn_start4;
private JButton btn_stop1;
private JButton btn_stop2;
private JButton btn_stop3;
private JButton btn_stop4;
private JPanel contentPane;
private MonitorPanel mPanel1;
private MonitorPanel mPanel2;
private MonitorPanel mPanel3;
private MonitorPanel mPanel4;
private MonitorPanelModel mpModel1;
private MonitorPanelModel mpModel2;
private MonitorPanelModel mpModel3;
private MonitorPanelModel mpModel4;
private JPanel panel_1;
private JPanel panel_2;
private JPanel panel_2_btn;
private JPanel panel_3;
private JPanel panel_3_btn;
private JPanel panel_4;
private JPanel panel_4_btn;
private boolean runFlag1 = false;
private boolean runFlag2 = false;
private boolean runFlag3 = false;
private boolean runFlag4 = false;
/**
* Create the frame.
*/
public MonitorPanelTest() {
setTitle("监控面板测试");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 1183, 681);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(new GridLayout(2, 2, 0, 0));
createMonitorPanel1();
createMonitorPanel2();
createMonitorPanel3();
createMonitorPanel4();
}
private void createMonitorPanel1() {
panel_1 = new JPanel();
contentPane.add(panel_1);
panel_1.setLayout(new BorderLayout(0, 0));
mpModel1 = new MonitorPanelModel();
mPanel1 = new MonitorPanel(mpModel1);
panel_1.add(mPanel1);
mpModel1.setMaxCoordinateCount(200);
mPanel1.setGraphTitle("0到10000之间的随机数");
JPanel panel_1_btn = new JPanel();
panel_1.add(panel_1_btn, BorderLayout.SOUTH);
JButton btn_start1 = new JButton("启 动");
btn_start1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
start1();
}
});
panel_1_btn.add(btn_start1);
btn_stop1 = new JButton("停 止");
btn_stop1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
runFlag1 = false;
}
});
panel_1_btn.add(btn_stop1);
btn_clear1 = new JButton("清 空");
btn_clear1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
mpModel1.clearCoordinate();
}
});
panel_1_btn.add(btn_clear1);
}
private void createMonitorPanel2() {
panel_2 = new JPanel();
contentPane.add(panel_2);
panel_2.setLayout(new BorderLayout(0, 0));
mpModel2 = new MonitorPanelModel();
mpModel2.setxAxisMode(XAxisMode.KEEP_MOVE);
mpModel2.setKeepMoveTimeInterval(10 * 60 * 1000L);
mpModel2.setMaxCoordinateCount(600);
mPanel2 = new MonitorPanel(mpModel2);
mPanel2.setGraphTitle("内存图测试");
mPanel2.setGraphBackgroundColor(new Color(38, 38, 38));
mPanel2.setGridLineColor(new Color(0, 225, 34));
mPanel2.setGraphLineColor(Color.YELLOW);
panel_2.add(mPanel2);
panel_2_btn = new JPanel();
panel_2.add(panel_2_btn, BorderLayout.SOUTH);
btn_start2 = new JButton("启 动");
btn_start2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
start2();
}
});
panel_2_btn.add(btn_start2);
btn_stop2 = new JButton("停 止");
btn_stop2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
runFlag2 = false;
}
});
panel_2_btn.add(btn_stop2);
btn_clear2 = new JButton("清 空");
btn_clear2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
mpModel2.clearCoordinate();
}
});
panel_2_btn.add(btn_clear2);
}
private void createMonitorPanel3() {
panel_3 = new JPanel();
contentPane.add(panel_3);
panel_3.setLayout(new BorderLayout(0, 0));
mpModel3 = new MonitorPanelModel();
mpModel3.setxAxisMode(XAxisMode.KEEP_MOVE);
mpModel3.setKeepMoveTimeInterval(10 * 60 * 1000L);
mpModel3.setMaxCoordinateCount(1200);
mPanel3 = new MonitorPanel(mpModel3);
mPanel3.setGraphTitle("递增递减");
panel_3.add(mPanel3, BorderLayout.CENTER);
panel_3_btn = new JPanel();
panel_3.add(panel_3_btn, BorderLayout.SOUTH);
btn_start3 = new JButton("启 动");
btn_start3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
start3();
}
});
panel_3_btn.add(btn_start3);
btn_stop3 = new JButton("停 止");
btn_stop3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
runFlag3 = false;
}
});
panel_3_btn.add(btn_stop3);
btn_clear3 = new JButton("清 空");
btn_clear3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
mpModel3.clearCoordinate();
}
});
panel_3_btn.add(btn_clear3);
}
private void createMonitorPanel4() {
panel_4 = new JPanel();
contentPane.add(panel_4);
panel_4.setLayout(new BorderLayout(0, 0));
mpModel4 = new MonitorPanelModel();
mpModel4.setxAxisMode(XAxisMode.KEEP_MOVE);
mpModel4.setKeepMoveTimeInterval(360 * 1000L);
mpModel4.setMaxCoordinateCount(720);
mpModel4.setyAxisMode(YAxisMode.FIXED);
mpModel4.setMaxYCoords(100L);
mpModel4.setMinYCoords(-100L);
mpModel4.setyAxisInterval(20L);
mPanel4 = new MonitorPanel(mpModel4);
panel_4.add(mPanel4, BorderLayout.CENTER);
mPanel4.setGraphTitle("正弦函数");
mPanel4.setGraphBackgroundColor(new Color(38, 38, 38));
mPanel4.setGridLineColor(new Color(0, 225, 34));
mPanel4.setGraphLineColor(Color.YELLOW);
panel_4_btn = new JPanel();
panel_4.add(panel_4_btn, BorderLayout.SOUTH);
btn_start4 = new JButton("启 动");
btn_start4.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
start4();
}
});
panel_4_btn.add(btn_start4);
btn_stop4 = new JButton("停 止");
btn_stop4.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
runFlag4 = false;
}
});
panel_4_btn.add(btn_stop4);
btn_clear4 = new JButton("清 空");
btn_clear4.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
mpModel4.clearCoordinate();
}
});
panel_4_btn.add(btn_clear4);
}
private void start1() {
runFlag1 = true;
Thread t = new Thread(new Runnable() {
@Override
public void run() {
int rint;
Random r = new Random();
while (runFlag1) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
rint = r.nextInt(10000);
mpModel1.addCoordinate(new Coordinate(System.currentTimeMillis(), rint + 1));
}
}
});
t.start();
}
private void start2() {
if (runFlag2) {
return;
}
runFlag2 = true;
Thread t = new Thread(new Runnable() {
@Override
public void run() {
Runtime rt = Runtime.getRuntime();
while (runFlag2) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
mpModel2.addCoordinate(new Coordinate(System.currentTimeMillis(), rt.freeMemory() / 1024 / 1024));
}
}
});
t.start();
}
private void start3() {
if (runFlag3) {
return;
}
runFlag3 = true;
Thread t = new Thread(new Runnable() {
@Override
public void run() {
boolean b = true;
int i = 0;
while (runFlag3) {
if (b) {
if (i < 100) {
i++;
} else {
b = !b;
}
} else {
if (i > 0) {
i--;
} else {
b = !b;
}
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
mpModel3.addCoordinate(new Coordinate(System.currentTimeMillis(), i));
}
}
});
t.start();
}
private void start4() {
if (runFlag4) {
return;
}
runFlag4 = true;
Thread t = new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
double d;
long l;
while (runFlag4) {
if (i == 360) {
i = 0;
}
d = Math.sin(Math.toRadians(i));
i++;
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
l = (long) (d * 100);
mpModel4.addCoordinate(new Coordinate(System.currentTimeMillis(), l));
}
}
});
t.start();
}
}