Recreate bar chart without it remembering data
Asked Answered
R

1

0

Task

I have a BarChart which I have to fill with different data over and over again. The data must be in a predefined order. Of course I only want to change the data and not create a bar chart every time.

Problem

Once you have a category with a given name that already existed in earlier data, the order is wrong.

I created an example. By clicking on the "Insert Before" button, a given number of bars is added. After that the "static" bar is added.

The "Insert After" button adds the "static" bar first and then the other bars.

public class BarChartSample extends Application {

    int count = 1;

    @Override
    public void start(Stage stage) {

        final CategoryAxis xAxis = new CategoryAxis();
        final NumberAxis yAxis = new NumberAxis();
        final BarChart<String, Number> bc = new BarChart<String, Number>(xAxis, yAxis);
        bc.setAnimated(false);

        // create new chart data where the data are inserted before the "static" bar
        Button insertBeforeButton = new Button("Insert Before");
        insertBeforeButton.setOnAction(e -> {

            XYChart.Series series1 = new XYChart.Series();

            for (int i = 0; i < count; i++) {
                series1.getData().add(new XYChart.Data("New " + i, 50));
            }

            series1.getData().add(new XYChart.Data("Static", 100));

            bc.getData().setAll(series1);

            count++;

        });

        // create new chart data where the data are inserted after the "static" bar
        Button insertAfterButton = new Button("Insert After");
        insertAfterButton.setOnAction(e -> {

            XYChart.Series series1 = new XYChart.Series();

            series1.getData().add(new XYChart.Data("Static", 100));

            for (int i = 0; i < count; i++) {
                series1.getData().add(new XYChart.Data("New " + i, 50));
            }

            bc.getData().setAll(series1);

            count++;

        });

        // borderpane for chart and toolbar
        BorderPane bp = new BorderPane();
        bp.setCenter(bc);

        // toolbar
        HBox hb = new HBox();
        hb.getChildren().addAll(insertBeforeButton, insertAfterButton);
        bp.setTop(hb);

        Scene scene = new Scene(bp, 400, 200);

        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

When you start the program and click on "Insert Before", you get this:

enter image description here

When you restart the program and click on "Insert After", you get this:

enter image description here

When you restart the program and click on "Insert Before" and then on "Insert After", you get this:

enter image description here

which is wrong. It should be this:

enter image description here

Is there a way to clear the barchart's memory? Obviously setData isn't sufficient.

I suspect it has something to do with the special removal methods in the bar chart and that the data weren't removed totally when the new data are added. There are some dubious methods like "seriesBeingRemovedIsAdded" in the source code of the BarChart class in JavaFX.

Thank you very much for the help!

Rheo answered 5/5, 2015 at 12:15 Comment(7)
Insert Before action will add a bar before the last bar i.e. static. Insert After will add a bar after the last bar i.e. again static. The logic seems correct to me. I do not understand how pressing Insert Before and then Insert After should result in the last image. What is the logic behind it?Irra
The buttons are badly named ("Insert" to me implies the result you see), but the logic of the code should result in the last image; he creates a new (empty) series, then adds "Static", then "New 0", then "New 1".Robinett
@ItachiUchiha: "Insert Before" should add ALL bars before the "static" bar. "Insert After" should add ALL bars after the "static" bar. Always, there shouldn't be a mix with some bars before the static and some after the static.Rheo
I just tried with adding a "Clear" button which does nothing else than getData().clear(). It's a race condition. When I click "Clear" first and then "Insert After", then the result is correct. So I guess the problem is more to invoke a getData().clear() method, then wait until all is cleared and then add the new data. Question is how to find out if the chart is fully cleared.Rheo
IMO you are right in your suspicion. If the names are changed for "New before " + i and "New after " + i in the loops, it works correct.Fardel
I think you should file this as a bug... even with @UlukBiy's workaround, it shouldn't work like this.Robinett
Ok, I created an issue.Rheo
F
4

Well.. again calling the layout() seems to solve the problem

bc.getData().clear();
bc.layout();
bc.getData().addAll( series1 );

in the "Insert After" second loop.

Fardel answered 5/5, 2015 at 13:4 Comment(1)
.clearValues(), not .clear(), if you guys are talking about MPAndroidChartUnclean

© 2022 - 2024 — McMap. All rights reserved.