如何使用JFreeChart动态更新图表?

时间:2015-08-20 23:56:27

标签: java swing jfreechart

我正在尝试动态生成图表,以显示随时间变化的值。我将这些值存储在ArrayList< Integer, ArrayList<Integer>>中,并在此类中检索这些值。但是,随着时间的推移,它并未显示ArrayList中的值的添加。

实际上另外两个线程正在更新ArrayList,我需要在动态图表中显示Arraylist的值。

以下是基于此example的代码:

package com.model.presentation;

import java.awt.BorderLayout;
import java.awt.Dimension;
//import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
//import java.util.Random;
import java.util.Map.Entry;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.Timer;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.DefaultCategoryDataset;

import com.model.resources.Household;

/**
 * @see https://stackoverflow.com/a/15715096/230513
 * @see https://stackoverflow.com/a/11949899/230513
 */

public class DisplayChart {

    //private static final int N = 128;
    //private static final Random random = new Random();
    private int n = 1;
    static int count = 0;

    public void display() 
    {
        JFrame f = new JFrame("Community Rescilience Model");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        final JTabbedPane jtp = new JTabbedPane();
        jtp.add(String.valueOf(n), createPane());
        f.add(jtp, BorderLayout.CENTER);
        JPanel p = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        p.add(new JButton(new AbstractAction("Add") {
            public void actionPerformed(ActionEvent e) {
                jtp.add(String.valueOf(++n), createPane());
                jtp.setSelectedIndex(n - 1);
            }
        }));
        f.add(p, BorderLayout.SOUTH);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    private ChartPanel createPane() 
    {
        final DefaultCategoryDataset dataset = new DefaultCategoryDataset();

        final String name = "Community ";

       /* for (int i = 0; i < random.nextInt(N) + N / 2; i++) 
        {

            while (iterator.hasNext()) 
            {
                Map.Entry map = (Map.Entry) iterator.next();
                String community_name =  name + String.valueOf(map.getKey());
                ArrayList<Integer> dataArrayList = (ArrayList<Integer>) map.getValue();
                for (Iterator<Integer> it = dataArrayList.iterator(); it.hasNext();)
                {
                    dataset.addValue(it.next(), community_name, String.valueOf(count));
                    count++;
                }
            }
         }*/
       // XYSeriesCollection dataset = new XYSeriesCollection(series);
        new Timer(100, new ActionListener() 
        {
            public void actionPerformed(ActionEvent e) 
            {
                Iterator<Entry<Integer, ArrayList<Integer>>> iterator = Household.goods.entrySet()
                        .iterator();
                while (iterator.hasNext()) 
                {
                    Map.Entry map = (Map.Entry) iterator.next();
                    String community_name =  name + String.valueOf(map.getKey());
                    ArrayList<Integer> dataArrayList = (ArrayList<Integer>) map.getValue();
                    for (Iterator<Integer> it = dataArrayList.iterator(); it.hasNext();)
                    {
                        dataset.setValue(it.next(), community_name, String.valueOf(count));
                        count++;
                    }
                 }
                }

         }).start();
        JFreeChart lineChart = ChartFactory.createLineChart("Resource Production/Consumption over time", "Time",
                "Number of GOODS", dataset, PlotOrientation.VERTICAL,
                true, true, false);
        return new ChartPanel(lineChart) {
            @Override
            public Dimension getPreferredSize() 
            {
                return new Dimension(1000, 500);
            }
        };
    }


    /*public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new DisplayChart().display();
            }
        });
    }
}*/

}

主要课程是:

public class Main_class {

public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            new DisplayChart().display();
        }
    });
}

此代码有效,但在某些时候,它会卡住。这意味着它不会显示Arraylist中的更改值。

1 个答案:

答案 0 :(得分:1)

我无限期地运行,虽然我不确定它是否仍按预期工作。

我没有家庭班,所以我只是假装它。

class Household {
    static public Map<Integer, ArrayList<Integer>> goods = new HashMap<>();
}

我也不认为我有用于向绘图添加数据的代码。我是这样做的:

Random rand = new Random();
while (true) {
    try {
        Thread.sleep(100);
        for (int i = 0; i < 10; i++) {
            final int fi = i;
            EventQueue.invokeLater(new Runnable() {
                public void run() {
                    ArrayList<Integer> l = Household.goods.get(fi);
                    if (l == null) {
                        l = new ArrayList<>();
                    }
                    l.add(rand.nextInt(100));
                    if (l.size() > 20) {
                        l.remove(0);
                    }
                    Household.goods.put(fi, l);
                }
            });
        }
    } catch (InterruptedException ex) {
    }
}

请注意,在EventQueue线程中执行它很重要,否则会出现ConcurrentModificationException。

真正的问题似乎是您在列表中一遍又一遍地添加相同的数据与不同的计数相关联。

所以我改变了:

    for (Iterator<Integer> it = dataArrayList.iterator(); it.hasNext();)
    {
           dataset.setValue(it.next(), community_name, String.valueOf(count));
           count++;
     }

致:

for (count = 0; count < dataArrayList.size(); count++) {
    dataset.setValue(dataArrayList.get(count), community_name, String.valueOf(count));
}