Dynamically update a pie chart in an Observer?

情到浓时终转凉″ 提交于 2020-01-25 07:22:06

问题


I am using pie chart to display some statistics in a JFrame using JFreeChart package. I am using the PieDataset to be passed to the createChart method. Also, the datatset is set to update dynamically, as I am using the observer pattern in my application, which I thoroughly debugged. My issue is that in spite of being able to update the datatset dynamically, the piechart on the frame does not update as it is, maybe not able to take the new (updated) values and display the result. I would like to know if there is some other way to update the pie-chart dynamically.

public void update(Observable observable, Object o) {
    if (o instanceof Game || o instanceof GameController) {
        String label = "<html><head><h1>World Domination View</h1></head><body> ";

        territoriesList = Game.getInstance().getGameMap().getTerritories();
        String[] name = new String[Game.getInstance().getNumPlayers()] ;
        Float[] value = new Float[Game.getInstance().getNumPlayers()];
        for (int i = 0; i < Game.getInstance().getNumPlayers(); i++) {
            int tempTerritoryCount = 0;
            float percentage = 0;

            for (Territory territory : territoriesList) {
                if (territory.getOwner() == Game.getInstance().getPlayerById(i)) {
                    tempTerritoryCount += 1;
                }
            }
            percentage = (float) 100.0 * tempTerritoryCount / Game.getInstance().getGameMap().getTerritories().size();
            label = label + Game.getInstance().getPlayerById(i).getName() + " owns " + percentage
                    + " % territories and owns " + PhaseView.getInstance().curPArmies + "<br/>";
            worldDominationViewLabel.setText(label);
            //dt = createDataset(Game.getInstance().getPlayerById(i).getName(),percentage);

            //createDataset(Game.getInstance().getPlayerById(i).getName(),percentage);
            //for(int j=0; j<Game.getInstance().getNumPlayers();j++){
                name[i] = Game.getInstance().getPlayerById(i).getName();
            //}
            if(name[i] != null)
        {
            value[i] = percentage;
        }


    }
    dt = createDataset(name,value);
    chartPanel = new ChartPanel(createChart(dt));
    chartPanel.setBounds(1024,0,310,300);//390
    chartPanel.setVisible(true);
    frameFromPhase.add(chartPanel);
    worldDominationViewLabel.setText(label + "</body></html>");}}

//the dataset definition
public static PieDataset createDataset(String[] plname,Float[] value){
    DefaultPieDataset dataset = new DefaultPieDataset();
    for(int i =0; i< plname.length;i++){
        dataset.setValue(plname[i],value[i]);

    }
    return dataset;
}

//chart definition
public static JFreeChart createChart(PieDataset dataset ) {
    JFreeChart chart = ChartFactory.createPieChart(
            "Player Map Domination: Territorywise",   // chart title
            dataset,          // data
            true,             // include legend
            true,
            false);

    return chart;
}

回答1:


As suggested here, don't create a new dataset and chart with each change; instead, "update the chart's data model, PieDataset, and the listening view will follow." An implementation of the Observer interface can update the chart's model in its update() method, just as well as the action handler of a JButton can. Starting from this complete example, I've added an empty pie chart to View and modified update() to track guesses by invoking setValue() on the chart's dataset.

class View extends JPanel {

    private static final String s = "Click a button.";
    private static final int SIZE = 256;
    private Model model;
    private ColorIcon icon = new ColorIcon(SIZE, Color.gray);
    private JLabel label = new JLabel(s, icon, JLabel.CENTER);
    DefaultPieDataset dataset = new DefaultPieDataset();

    public View(Model model) {
        super(new BorderLayout());
        this.model = model;
        label.setVerticalTextPosition(JLabel.BOTTOM);
        label.setHorizontalTextPosition(JLabel.CENTER);
        this.add(label, BorderLayout.CENTER);
        this.add(genButtonPanel(), BorderLayout.SOUTH);
        PiePlot plot = new PiePlot(dataset);
        plot.setSimpleLabels(true);
        JFreeChart chart = new JFreeChart(null, null, plot, false);
        this.add(new ChartPanel(chart) {
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(SIZE, SIZE);
            }
        }, BorderLayout.WEST);
        model.addObserver(new ModelObserver());
    }
    …    
    private class ModelObserver implements Observer {

        private int pass, fail;

        @Override
        public void update(Observable o, Object arg) {
            if (arg == null) {
                label.setText(s);
                icon.color = Color.gray;
            } else {
                if ((Boolean) arg) {
                    label.setText("Win!");
                    dataset.setValue("Pass", ++pass);
                } else {
                    label.setText("Keep trying.");
                    dataset.setValue("Fail", ++fail);
                }
            }
        }
    }
    …
}


来源:https://stackoverflow.com/questions/55459036/dynamically-update-a-pie-chart-in-an-observer

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