Hiding Legend for Zero Chart Values ​​javaFX Elements

I'm new to the forums, so I hope I'm not asking the question that has been answered in the past. I tried to find an answer before posting.

I am currently working on a pie chart that will eventually be used to track financial expenses. Now I have several categories that make up each piece. I am trying to hide the legend for zero value slices.

I am doing this in javaFX. I am still very green when it comes to programming and have no experience outside of Java. Any help explained to the mannequins would be appreciated. Thank.

Added a picture and complete code to illustrate the problem. Restaurants and restaurants, as well as shopping and entertainment, have zero values. I want to hide the legend for these items in this example.

package Example;

import java.net.URL;
import java.util.ResourceBundle;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.chart.PieChart;

public class PieExampleController implements Initializable {

@FXML
private PieChart pieChart;

@Override
public void initialize(URL arg0, ResourceBundle arg1) {
    // TODO Auto-generated method stub

    ObservableList<PieChart.Data> pieChartData = FXCollections.observableArrayList(
            new PieChart.Data("Groceries", 1),
            new PieChart.Data("Transportation", 1),
            new PieChart.Data("Restaurants & Dining", 0),
            new PieChart.Data("Shopping & Entertainment", 0));

        pieChart.setData(pieChartData);

}
}

      

enter image description here

+3


source to share


2 answers


This is how I do it:



    List<PieChart.Data> dataArrayList = new LinkedList<Data>();
    if (value1>0) {
            Data data = new PieChart.Data("my label", value1);
            dataArrayList.add(data);
    }
     ...

    ObservableList<PieChart.Data> pieChartData = 
    FXCollections.observableArrayList(dataArrayList);

      

0


source


Adding only non-empty data records (or removing empty records) manually once at startup is just fine if the data is immutable and unmodifiable. On the other hand, if this can change over the lifetime of the chart, we need a mechanism that automatically handles the add / remove: FilteredList to the rescue.

Below is an example that

  • configures the original list with an extractor (on pieValueProperty): this will be notified about the change of this value with a change in the update type using the listChangeListener function
  • wraps FilteredList around the original list
  • configures pieChart with a filtered list

With this we can set a predicate in the filterList file that hides elements as needed: the example uses a slider to update the bottom value, whose value should be included in the chart.

Unfortunately, PieChart has a couple of bugs (sigh ... whatever I touch in FX, they always brew ...) that get in the way of such an easy installation



  • due to a fancy node / value mixture plus an "optimized" internal data structure plus an incorrect implementation of synchronization of the internal (linked) data structure with changes in the list, the graph cannot be animated
  • sync cannot handle type changes being replaced at all (this is what FilteredList fires when the predicate is reset)

In the example, both problems can be avoided by disabling the animation and clearing the list (set a predicate that blocks everything) before setting the real state. In the product code, this setting may or may not be possible.

Example:

public class FilteredPieChartExample extends Application {

    @Override
    public void start(Stage primaryStage) {

        FilteredList<Data> filtered = getChartData();
        //ListChangeReport report = new ListChangeReport(filtered);

        PieChart pieChart = new PieChart(filtered);
        // bug in pieChart: can't handle data modification with animation on
        pieChart.setAnimated(false);

        // use slider to set lower threshhold for value of data to show in pie
        Slider slider =  new Slider(-1., 100., -1.);
        slider.valueProperty().addListener((src, ov, nv) -> {
            // actually, cannot handle data modification at all ... need to clear out first ...
            // bug in pieChart.dataChangeListener: doesn't handle replaced correctly
            filtered.setPredicate(data -> false);
            filtered.setPredicate(data -> data.getPieValue() > nv.doubleValue());
            //report.prettyPrint();
        });
        primaryStage.setTitle("PieChart");
        Pane root = new VBox(pieChart, slider); 
        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private FilteredList<Data> getChartData() {
        // use ObservableList with extractor on pieValueProperty
        ObservableList<Data> answer = FXCollections.observableArrayList(
                e -> new Observable[] {e.pieValueProperty()}
                );
        answer.addAll(
                new Data("java", 17.56), 
                new Data("C", 17.06), 
                new Data("C++", 8.25), 
                new Data("C#", 8.20), 
                new Data("ObjectiveC", 6.8), 
                new Data("PHP", 6.0), 
                new Data("(Visual)Basic", 4.76),
                new Data("Other", 31.37),
                new Data("empty", 0)
                );
        return new FilteredList<>(answer);
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

    @SuppressWarnings("unused")
    private static final Logger LOG = Logger.getLogger(FilteredPieChartExample.class
            .getName());

}

      

0


source







All Articles