swing开发数据变化折线图(显示0时到当前时间的)
- 案例:详细描述
- 效果图片
- 折线图工具类
- 重绘下拉选择框
- 测试类
- 数据类
- 实体类
案例:详细描述
需求要求定时刷新该折线图,只展示此刻之前的数据,但横坐标要求显示一天0点到23点。
效果图片
图片:
折线图工具类
XyChartFacDemo .java
package xny.hyd.tool;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.labels.XYItemLabelGenerator;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.time.Day;
import org.jfree.data.time.Hour;
import org.jfree.data.time.Minute;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.xy.XYDataset;
import xny.hyd.entity.ChartData;
import xny.hyd.entity.MaxMinCoordinat;
import xny.tool.NewJComboBox;
/**
* 折线图基类
* 2019年8月28日08:44:47
* @author Administrator
*
*/
public class XyChartFacDemo {
//定义整个界面panel
private JPanel contentPane;
//折线图变量
// private JFreeChart xylineChart = null;
//全部数据
public List<ChartData> date = null;
//当前要展示数据
public List<ChartData> dateNow = null;
//折线图图表
private JFreeChart lineChart;
//数据集
private TimeSeriesCollection dataset;
//每一条折线的最大最小值
public List<MaxMinCoordinat> value;
//是否需要顯示
private boolean isShowX;
//是否要查询条件
private boolean isHaveSelect = false;
//每隔多长时间一个数据点
private int timeinterval = 15;
//已知数据点时间长度,算出一天之内有多少个数据点/一天之内的总数据点个数
private int dataPoint = (24*60)/timeinterval;
//下拉数据
private List<String> selectData = new ArrayList<String>();
private String[] list;
public boolean isHaveSelect() {
return isHaveSelect;
}
public void setHaveSelect(boolean isHaveSelect) {
this.isHaveSelect = isHaveSelect;
}
public int getTimeinterval() {
return timeinterval;
}
public void setTimeinterval(int timeinterval) {
this.timeinterval = timeinterval;
}
public List<String> getSelectData() {
return selectData;
}
public void setSelectData(List<String> selectData) {
this.selectData = selectData;
}
/**
* 构造方法
*/
public XyChartFacDemo() {
this(false);
}
public XyChartFacDemo(boolean isShowX) {
this.isShowX = isShowX;
date = new ArrayList<ChartData>();
dateNow = new ArrayList<ChartData>();
}
public void init() {
if(selectData!=null&&selectData.size()>0) {
list = new String[selectData.size()];
for(int i=0;i<selectData.size();i++) {
list[i]=selectData.get(i);
}
}
}
/**
* 重新查询数据,刷新折线图
*/
public void zxtPushData() {
//查询数据
//数据处理
//刷新折线图
// LineChart push = new LineChart();
}
/**
* Create the frame.
* 获取一个折线图jpanel
*/
public JPanel getChooseshow(List<ChartData> dateList) {
contentPane = new JPanel();
contentPane.setOpaque(false);
contentPane.setLayout(new BorderLayout(0, 0));
getDate(dateList);
//获取折线图
LineChart xy = new LineChart();
ChartPanel charpanal = xy.getCharPanel(createDataset(dateList));
contentPane.add(charpanal,BorderLayout.CENTER);
JPanel top = new JPanel();
top.setLayout(new BorderLayout(0, 0));
top.setOpaque(false);
contentPane.add(top, BorderLayout.NORTH);
//放多选框按钮
JPanel panel_2 = new JPanel();
panel_2.setOpaque(false);
panel_2.setLayout(new BoxLayout(panel_2, BoxLayout.X_AXIS));
top.add(panel_2, BorderLayout.WEST);
if(isHaveSelect) {
top.add(getCz(),BorderLayout.CENTER);
}
//循环添加选择框,并注册响应事件
for (int i = 0; i < dateList.size(); i++) {
JCheckBox checkBox = new JCheckBox(dateList.get(i).getName());
checkBox.setOpaque(false);
checkBox.setForeground(Color.decode(dateList.get(i).getColor()));
checkBox.setFont(new Font("苹方字体", Font.PLAIN, 17));
checkBox.setSelected(true);
checkBox.setName(dateList.get(i).getName());
panel_2.add(checkBox);
//入库流量选择框触发事件
checkBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
JCheckBox check = (JCheckBox) e.getSource();
// TODO Auto-generated method stub
if(!check.isSelected()) {
List<ChartData> xqlist = new ArrayList<ChartData>();
for (ChartData rk : dateNow) {
if(check.getName()!=null&&!"".equals(check.getName())) {
if(!check.getName().equals(rk.getName())) {
xqlist.add(rk);
}
}
}
dateNow = xqlist;
updateDate(createDataset(dateNow));
}else {
for (ChartData rk : date) {
if(check.getName()!=null&&!"".equals(check.getName())) {
if(check.getName().equals(rk.getName())) {
dateNow.add(rk);
}
}
}
updateDate(createDataset(dateNow));
}
}
});
}
return contentPane;
}
/**
* 厂站
* @return
*/
private JPanel getCz() {
//厂站
JPanel cz = new JPanel();
cz.setOpaque(false);
JLabel label_1 = new JLabel("厂(场)站:");
label_1.setFont(new Font("宋体", Font.PLAIN, 20));
label_1.setForeground(Color.WHITE);
cz.add(label_1);
// String[] czlist = new String[]{"全部"};
init();
final JComboBox box = new JComboBox(list);
box.setPreferredSize(new Dimension(150, 25));
box.setUI(new NewJComboBox());
box.setBackground(Color.decode("#1A5C63"));
box.setForeground(Color.white);
box.setBorder(BorderFactory.createLineBorder(Color.decode("#1A5C63"),1));
((JTextField) box.getEditor().getEditorComponent()).setBackground(Color.decode("#1A5C63"));
((JTextField) box.getEditor().getEditorComponent()).setForeground(Color.WHITE);
// 添加条目选中状态改变的监听器
box.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
// 只处理选中的状态
if (e.getStateChange() == ItemEvent.SELECTED) {
System.out.println("选中: " + box.getSelectedIndex() + " = " + box.getSelectedItem());
}
}
});
box.setEditable(true);
box.setSelectedIndex(1);
cz.add(box);
return cz;
}
/**
* 数据库获取数据
*/
public void getDate(List<ChartData> dateList) {
date = dateList;
dateNow = dateList;
}
/**
* 数据出力
* @return
*/
public XYDataset createDataset(List<ChartData> pushdata)
{
//刷新时根据勾选按钮刷新,只重新装载勾中的框的 数据
List<ChartData> data = new ArrayList<ChartData>();
for(int i=0;i<pushdata.size();i++) {
int t =0;
for(int j =0;j<dateNow.size();j++) {
if(pushdata.get(i).getName().equals(dateNow.get(j).getName())) {
t++;
}
}
if(t>0) {
data.add(pushdata.get(i));
}
}
dataset = new TimeSeriesCollection( );
value = new ArrayList<MaxMinCoordinat>();
Hour day = new Hour(0, new Day());
for(int i=0;i<data.size();i++) {
TimeSeries series = new TimeSeries( data.get(i).getName(),Minute.class );
double max = 0;
int ymax=0;
double min = 100000000;
int ymin=0;
Minute hour22 = new Minute(0, day);
int count = data.get(i).getDataList().size();//折线的数据量
for (int j=0;j<dataPoint;j++) {//一天之内的总数据点个数
if(j<count) {
if(max<data.get(i).getDataList().get(j).getYvalue()) {
max = data.get(i).getDataList().get(j).getYvalue();
ymax = j;
}
if(min>data.get(i).getDataList().get(j).getYvalue()) {
min = data.get(i).getDataList().get(j).getYvalue();
ymin = j;
}
series.add(hour22, data.get(i).getDataList().get(j).getYvalue());
}else {
series.add(hour22, null );
}
for(int t=0;t<timeinterval;t++) {
hour22 = ( Minute ) hour22.next();
}
}
dataset.addSeries(series);
MaxMinCoordinat maxVal = new MaxMinCoordinat();
maxVal.setRow(1);//0:最小值 1:最大值
maxVal.setXcoord(i);
maxVal.setYcoord(ymax);
value.add(maxVal);
MaxMinCoordinat minVal = new MaxMinCoordinat();
minVal.setRow(0);//0:最小值 1:最大值
minVal.setXcoord(i);
minVal.setYcoord(ymin);
value.add(minVal);
}
return dataset;
}
/**
* 刷新数据
* @param dataset
* @param color
* @return
*/
public void updateDate(XYDataset dataset) {
//刷新时根据勾选按钮刷新,只重新装载勾中的框的 数据
XYPlot plot = (XYPlot)lineChart.getPlot();
plot.setDataset(dataset);
XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer) plot.getRenderer();// 设置样式
for(int i=0;i<dateNow.size();i++) {
renderer.setSeriesPaint( i , Color.decode(dateNow.get(i).getColor()));
renderer.setSeriesStroke( i , new BasicStroke( 2.0f ) );
renderer.setSeriesItemLabelPaint(i, Color.decode(dateNow.get(i).getColor()));
}
}
class LineChart
{
/**
* 获取一个折线图
* @return
*/
public void getjfreechar(XYDataset data) {
lineChart = ChartFactory.createTimeSeriesChart(
"",
"",
"",
data,
false,true,false);
lineChart.setBorderVisible(false);
lineChart.setBackgroundPaint(null);
lineChart.setBorderPaint(Color.red);
lineChart.setBorderStroke(null);
XYPlot plot = (XYPlot) lineChart.getPlot();
plot.setRangeZeroBaselineVisible(true);
// plot.getDomainAxis().setLowerMargin(0.02);//数据区距离左右的距离
// plot.getDomainAxis().setUpperMargin(0.01);
plot.getDomainAxis().setLowerMargin(0.0D);//数据区距离左右的距离
plot.getDomainAxis().setUpperMargin(0.0D);
plot.setDomainGridlinesVisible(false);//竖直网格线隐藏
plot.setBackgroundAlpha(0);
plot.setOutlineVisible(false);//数据区黑色边框不可见
plot.getDomainAxis().setAxisLinePaint(Color.decode("#3CB5FC"));// X坐标轴颜色
// 设置网格横线颜色
plot.setRangeGridlinePaint(Color.decode("#1D566E"));
plot.setRangeGridlineStroke(new BasicStroke(2));
//x轴设置
// DateAxis domainAxis = (DateAxis) plot.getDomainAxis();
// domainAxis.setTickUnit(new DateTickUnit(DateTickUnit.HOUR, 1, new SimpleDateFormat("HH:mm")));//设置x轴一个小时一个刻度
if(isShowX) {//显示横坐标刻度值
plot.getDomainAxis().setTickLabelPaint(Color.decode("#00F4FC"));
}else {
plot.getDomainAxis().setTickLabelsVisible(false);
}
plot.getDomainAxis().setTickMarksVisible(false);
plot.getDomainAxis().setAxisLinePaint(Color.decode("#1D566E"));//x轴颜色
plot.getDomainAxis().setAxisLineStroke(new BasicStroke(2));
// categoryAxis.setVisible(false);
// 取得纵轴
plot.getRangeAxis().setAxisLineVisible(false);
plot.getRangeAxis().setTickMarksVisible(false);
NumberAxis numberAxis = (NumberAxis) plot.getRangeAxis();
// numberAxis.setTickUnit(new NumberTickUnit(100));//纵轴每100一个刻度
numberAxis.setTickLabelPaint(Color.decode("#13BBBF"));
numberAxis.setUpperMargin(0.15);//设置最高数据显示与顶端的距离
numberAxis.setLowerMargin(2);//设置最低的一个值与图片底端的距离
numberAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits() );
//设置折线颜色
@SuppressWarnings("serial")
XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer() {
@Override
public boolean getItemShapeVisible(int series, int item) {
// TODO Auto-generated method stub
boolean ret = false;
for (MaxMinCoordinat val : value) {
if(val.getXcoord() == series&&val.getYcoord() == item) {//最大值
ret = true;
return ret;
}else {
ret = false;
}
}
return ret;
}
};
XYItemLabelGenerator st = new XYItemLabelGenerator(){
@Override
public String generateLabel(XYDataset dataset, int row, int column) {
// TODO Auto-generated method stub
// double value = (Double) (dataset.getValue(row, column));
String ret = "";
for (MaxMinCoordinat val : value) {
if(val.getRow()==1&&val.getXcoord() == row&&val.getYcoord() == column) {//最大值
ret = "max:"+dataset.getYValue(row, column);
return ret;
}else if(val.getRow()==0&&val.getXcoord() == row&&val.getYcoord() == column) {//最小值
ret = "min:"+dataset.getYValue(row, column);
return ret;
}else {
ret = "";
}
}
return ret;
}
/*@Override
public String generateLabel(XYDataset arg0, int arg1, int arg2) {
// TODO Auto-generated method stub
return null;
}*/
};
renderer.setBaseItemLabelGenerator(st);
for(int i=0;i<dateNow.size();i++) {
renderer.setSeriesPaint( i , Color.decode(dateNow.get(i).getColor()));
renderer.setSeriesStroke( i , new BasicStroke( 2.0f ) );
renderer.setSeriesItemLabelPaint(i, Color.decode(dateNow.get(i).getColor()));
// renderer.setSeriesShape(new Shape());
}
renderer.setBaseItemLabelsVisible(true);
renderer.setDrawOutlines(true);
renderer.setBaseShapesVisible(true);// 设置拐点是否可见/是否显示拐点
plot.setRenderer(renderer);
}
/**
* 获取ChartPanel
* @param width
* @param heigh
* @return
*/
public ChartPanel getCharPanel(XYDataset data) {
getjfreechar(data);
ChartPanel chartPanel = new ChartPanel( lineChart );
// chartPanel.setPreferredSize( new java.awt.Dimension( width , heigh ) );
chartPanel.setOpaque(false);
chartPanel.setMouseZoomable( true , false );
return chartPanel;
}
}
public JFreeChart getLineChart() {
return lineChart;
}
public void setLineChart(JFreeChart lineChart) {
this.lineChart = lineChart;
}
}
XyChartFacDemo类生成折线图,并处理数据。
重绘下拉选择框
NewJComboBox.java
package xny.tool;
import javax.swing.*;
import javax.swing.plaf.basic.BasicButtonUI;
import javax.swing.plaf.basic.BasicComboBoxUI;
import javax.swing.plaf.basic.BasicComboPopup;
import javax.swing.plaf.basic.ComboPopup;
import java.awt.*;
/**
* 重绘下拉选择框
* 2019年9月16日15:18:59
*
* @author Administrator
*
*/
public class NewJComboBox extends BasicComboBoxUI {
private static ImageIcon DOWN_ICON = new ImageIcon("prjs/xny/src/xny/hyd/images/jComboBox.png");
private static Color DEFAULT_COLOR = new Color(150, 207, 254);
@Override
public void installUI(JComponent c) {
super.installUI(c);
JComboBox comboBox = (JComboBox) c;
comboBox.setFocusable(true);
comboBox.setOpaque(false);
comboBox.setRenderer(new MyListCellRenderer());
}
@Override
protected JButton createArrowButton() {
// 也可以使用BasicComboBoxUI里的arrowButton对象
JButton arrow = new JButton();
// 设置自己定义的UI
arrow.setUI(new MyButtonUI());
// 设置图标
arrow.setIcon(DOWN_ICON);
// 设置无法获得焦点
arrow.setFocusable(false);
// 设置边距,调整图标位置
arrow.setMargin(new Insets(0, 0, 0, 0));
return arrow;
}
@Override
public void paint(Graphics g, JComponent c) {
// 也可以使用BasicComboBoxUI里的combobox对象
JComboBox comboBox = (JComboBox) c;
hasFocus = comboBox.hasFocus();
Rectangle r = rectangleForCurrentValue();
// JComboBox的textfield的绘制,并不是靠Renderer来控制
// 它会通过paintCurrentValueBackground来绘制背景
// 然后通过paintCurrentValue去绘制显示的值
Graphics2D g2d = (Graphics2D) g;
if (!comboBox.isEditable()) {
paintCurrentValueBackground(g2d, r, hasFocus);
paintCurrentValue(g2d, r, hasFocus);
} else {
paintCurrentValueBackground(g2d, r, hasFocus);
}
// 获取焦点时,用不同颜色来区分
if (comboBox.hasFocus()) {
g2d.setColor(DEFAULT_COLOR);
} else {
g2d.setColor(Color.GRAY);
}
// 边框透明度
//g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
// 绘制边框,后两个参数控制圆角
// 边框也有占位,所以宽高都需要减去2,否则会导致边框不全
g2d.drawRoundRect(0, 0, comboBox.getWidth() - 2, comboBox.getHeight() - 1, 2, 2);
}
@Override
protected ComboPopup createPopup() {
BasicComboPopup popup = (BasicComboPopup) super.createPopup();
// 获取到popup,为其设置边框,和combobox的颜色保持同步
popup.setBorder(BorderFactory.createLineBorder(DEFAULT_COLOR));
return popup;
}
}
/**
* Created by SongFei on 2017/11/1.
*/
class MyButtonUI extends BasicButtonUI implements SwingConstants {
@Override
public void installUI(JComponent c) {
super.installUI(c);
JButton button = (JButton) c;
button.setContentAreaFilled(false);//父类不用绘制内容
button.setFocusPainted(false);//父类不用绘制焦点
button.setBorderPainted(false);//父类不用绘制边框
}
}
/**
* Created by SongFei on 2017/11/2.
*/
class MyListCellRenderer implements ListCellRenderer {
private DefaultListCellRenderer defaultCellRenderer = new DefaultListCellRenderer();
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
// 每一行,都转换成jlabel来处理
JLabel renderer = (JLabel) defaultCellRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
// 每一行的jlabel的颜色
if (isSelected) {
renderer.setBackground(new Color(150, 207, 254));
renderer.setForeground(Color.WHITE);
} else {
renderer.setBackground(null);
}
// 字体靠左
renderer.setHorizontalAlignment(JLabel.LEFT);
// 左侧padding
renderer.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 0));
// render的宽高
renderer.setPreferredSize(new Dimension(100, 25));
// list背景色,也就是向下的按钮左边儿那一块儿
list.setSelectionBackground(Color.decode("#1A5C63"));
list.setSelectionForeground(Color.WHITE);
list.setBorder(null);
return renderer;
}
}
测试类
TestLineChar.java
package xny.hyd.test;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import xny.hyd.tool.XyChartFacDemo;
/**
* 测试类
* 2019年9月19日16:42:37
* @author Administrator
*
*/
@SuppressWarnings("serial")
public class TestLineChar extends JFrame {
private JPanel contentPane;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
TestLineChar frame = new TestLineChar();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public TestLineChar() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 650, 400);
contentPane = new JPanel(new BorderLayout());
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setBackground(Color.decode("#12343B"));
XyChartFacDemo line = new XyChartFacDemo(true);
contentPane.add(line.getChooseshow(TestData.getDateBssw()));
setContentPane(contentPane);
}
}
数据类
TestLineChar.java
package xny.hyd.test;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import xny.hyd.entity.ChartProperty;
import xny.hyd.entity.ChartData;
public class TestData {
/**
* 数据库获取数据
*/
public static List<ChartData> getDateBssw() {
List<ChartData> returndate = new ArrayList<ChartData>();
ChartData line = new ChartData();
line.setName("坝上水位");
line.setColor("#FFFD38");
List<ChartProperty> dateList1 = new ArrayList<ChartProperty>();
for(int i=0;i<52;i++) {
ChartProperty d1 = new ChartProperty();
d1.setYvalue(Double.parseDouble(new Random().nextInt(400)+""));
d1.setChartName("坝上水位");
d1.setXvalue(""+i);
dateList1.add(d1);
}
line.setDataList(dateList1);
returndate.add(line);
return returndate;
}
}
实体类
ChartData.java
package xny.hyd.entity;
import java.util.List;
/**
* 图表数据
* 2019年9月16日15:21:14
* @author Administrator
*
*/
public class ChartData {
private String id;//id
private String name;//图表中每类数据的名称
private String color;//颜色
private List<ChartProperty> dataList;//数据
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public List<ChartProperty> getDataList() {
return dataList;
}
public void setDataList(List<ChartProperty> dataList) {
this.dataList = dataList;
}
}
ChartProperty.java
package xny.hyd.entity;
/**
* 降雨实体
* 2019年9月16日15:21:23
* @author Administrator
*
*/
public class ChartProperty {
//纵坐标
private Double yvalue;
//横坐标
private String xvalue;
//图表名类型
private String chartName;
public Double getYvalue() {
return yvalue;
}
public void setYvalue(Double yvalue) {
this.yvalue = yvalue;
}
public String getXvalue() {
return xvalue;
}
public void setXvalue(String xvalue) {
this.xvalue = xvalue;
}
public String getChartName() {
return chartName;
}
public void setChartName(String chartName) {
this.chartName = chartName;
}
}
MaxMinCoordinat.java
package xny.entity;
/**
* 最大最小值
* 2019年9月16日15:21:31
* @author Administrator
*
*/
public class MaxMinCoordinat {
// private
private int row;
private int xcoord;//横坐标
private int ycoord;//纵坐标
public int getXcoord() {
return xcoord;
}
public void setXcoord(int xcoord) {
this.xcoord = xcoord;
}
public int getYcoord() {
return ycoord;
}
public void setYcoord(int ycoord) {
this.ycoord = ycoord;
}
public int getRow() {
return row;
}
public void setRow(int row) {
this.row = row;
}
}
1、此案例可以生成各种各样的折线图,根据数据变化而变化。
2、同时根据折线条数生成图例、显示最大最小值、仅显示最大最小值数据点。
3、当取消图例勾选时同步刷新折线(如图所示)
例: