Dynamically repaint ScatterPlot in jfreechart

与世无争的帅哥 提交于 2019-12-13 00:26:41

问题


I have a scatterplot which plots positions of agents. These positions change. I was wondering how can I repaint/redraw the scatterplot with the new positions

my drawing method. I need to redraw in the updatePositions function. Is there any way to implement any listener for ScatterPlot?

private ChartPanel createPanel() {
    JFreeChart jfreechart = ChartFactory.createScatterPlot(
            title, "", "", initPositions(),PlotOrientation.VERTICAL, true, true, false);
    XYPlot xyPlot = (XYPlot) jfreechart.getPlot();
    xyPlot.setDomainCrosshairVisible(true);
    xyPlot.setRangeCrosshairVisible(true);
    XYItemRenderer renderer = xyPlot.getRenderer();
    renderer.setSeriesPaint(0, Color.blue);
    adjustAxis((NumberAxis) xyPlot.getDomainAxis(), true);
    adjustAxis((NumberAxis) xyPlot.getRangeAxis(), false);
    xyPlot.setBackgroundPaint(Color.white);
    return new ChartPanel(jfreechart);
}

private void adjustAxis(NumberAxis axis, boolean vertical) {
    axis.setRange(-1, lattice+1);
    axis.setTickUnit(new NumberTickUnit(1));
    axis.setVerticalTickLabels(vertical);
}

private XYDataset initPositions() {
    XYSeriesCollection xySeriesCollection = new XYSeriesCollection();

    for (int i = 0; i < populationSize; i++) {
        if(population.get(i).status==1){
            healthy.add(population.get(i).position[0], population.get(i).position[1]);
        }else if(population.get(i).status==2){
            infected.add(population.get(i).position[0], population.get(i).position[1]);
        }else if(population.get(i).status==3){
            recovered.add(population.get(i).position[0], population.get(i).position[1]);
        }
    }

    xySeriesCollection.addSeries(healthy);
    xySeriesCollection.addSeries(infected);
    xySeriesCollection.addSeries(recovered);
    return xySeriesCollection;
}

public void clear(){
    healthy.clear();
    infected.clear();
    recovered.clear();
}
public void updatePositions(ArrayList<Person> pop ){
    population = pop;

    for (int i = 0; i < populationSize; i++) {
        if(population.get(i).status==1){
            healthy.addOrUpdate(population.get(i).position[0], population.get(i).position[1]);
        }else if(population.get(i).status==2){
            infected.addOrUpdate(population.get(i).position[0], population.get(i).position[1]);
        }else if(population.get(i).status==3){
            recovered.addOrUpdate(population.get(i).position[0], population.get(i).position[1]);
        }
    }
}

this is the method in the main class. The update of the positions is done at the "move" function

    public static void main(String [] args){
    createPopulation(populationSize);
    initInfection(infectRatio);

    EventQueue.invokeLater(new Runnable() {             
        @Override           
        public void run() {         
            DrawArea demo = new DrawArea("Demo", lattice, populationSize,population);               
            demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);                
            demo.pack();                
            demo.setLocationRelativeTo(null);               
            demo.setVisible(true);
            for(int i =0;i<1000;i++){

                for(int j=0; j<populationSize; j++){
                    population.get(j).move(0.8);
                }
                demo.clear();
                demo.updatePositions(population);
            }
        }          
    });
}

回答1:


As shown below, the chart (view) listens to its dataset (model) and updates itself accordingly. When the Move button is pressed, each XYDataItem in the series in modified in update() to reflect its new position.

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.util.*;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.jfree.chart.*;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.data.xy.XYDataItem;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

/**
 * @see http://stackoverflow.com/a/19749344/230513
 * @see http://stackoverflow.com/a/7208723/230513
 */
public class ScatterMove extends JFrame {

    private static final int N = 16;
    private static final String title = "Scatter Move Demo";
    private static final Random rand = new Random();
    private XYSeries moved = new XYSeries("Population");

    public ScatterMove(String s) {
        super(s);
        update();
        final ChartPanel chartPanel = createDemoPanel();
        this.add(chartPanel, BorderLayout.CENTER);
        JPanel control = new JPanel();
        control.add(new JButton(new AbstractAction("Move") {
            @Override
            public void actionPerformed(ActionEvent e) {
                moved.clear();
                update();
            }
        }));
        this.add(control, BorderLayout.SOUTH);
    }

    private void update() {
        for (int i = 0; i < N; i++) {
            moved.add(new XYDataItem(rand.nextGaussian(), rand.nextGaussian()));
        }
    }

    private ChartPanel createDemoPanel() {
        JFreeChart jfreechart = ChartFactory.createScatterPlot(
            title, "X", "Y", createSampleData(),
            PlotOrientation.VERTICAL, true, true, false);
        XYPlot xyPlot = (XYPlot) jfreechart.getPlot();
        XYItemRenderer renderer = xyPlot.getRenderer();
        NumberAxis domain = (NumberAxis) xyPlot.getDomainAxis();
        domain.setRange(-3.0, 3.0);
        domain.setTickUnit(new NumberTickUnit(1));
        NumberAxis range = (NumberAxis) xyPlot.getRangeAxis();
        range.setRange(-3.0, 3.0);
        range.setTickUnit(new NumberTickUnit(1));
        return new ChartPanel(jfreechart){

            @Override
            public Dimension getPreferredSize() {
                return new Dimension(640, 480);
            }
        };
    }

    private XYDataset createSampleData() {
        XYSeriesCollection xySeriesCollection = new XYSeriesCollection();
        xySeriesCollection.addSeries(moved);
        return xySeriesCollection;
    }

    public static void main(String args[]) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                ScatterMove demo = new ScatterMove(title);
                demo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                demo.pack();
                demo.setLocationRelativeTo(null);
                demo.setVisible(true);
            }
        });
    }
}


来源:https://stackoverflow.com/questions/19740018/dynamically-repaint-scatterplot-in-jfreechart

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!