Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove JavaFX 2 LineChart Legend Items

I have a line chart with many series. These series are grouped into one or more super-series. Each super-series may have many "breaks" in the line in order to accurately depict when a monitor process is not actively collecting data. Each data break is actually starting a new series.

I have been able to successfully overcome several technical issues with this such as the chart assigning a new color to each new series, chart line symbol color not matching the series color, etc. All is working quite well right now, except that each time I add a new series to the chart, it adds an item to the legend.

Is there a way to remove items from the legend, or do I have to hide the default legend and add my own custom legend pane?

like image 278
RonSiven Avatar asked Jan 07 '14 22:01

RonSiven


2 Answers

Don't show the legend:

chart.setLegendVisible(false);

You can then create your own custom pane to make your own legend and render it how you wish.

like image 171
jewelsea Avatar answered Sep 24 '22 03:09

jewelsea


After several failed attempts at implementing various suggestions, I found that the best way to allow a user to show/hide a data series in a JavaFx Chart (or sub-classes thereof) is to extend the chart class you want to use and override its updateLegend() method.

It's quite simple actually. Here's an example using a basic HBox as the legend containing check boxes as the legend items. In this example I have decided to make my LineChart with fixed axes types (CategoryAxis and NumberAxis). You might choose to leave your sub-class with generics for axes.

public class AtopLineChart<X, Y> extends LineChart<String, Number>
{

   /**
    * @param xAxis
    * @param yAxis
    */
   public AtopLineChart(final CategoryAxis xAxis, final NumberAxis yAxis)
   {
      super(xAxis, yAxis);
   }

   /* (non-Javadoc)
    * @see javafx.scene.chart.LineChart#updateLegend()
    */
   @Override
   protected void updateLegend()
   {
      final HBox legend = new HBox();
      legend.setVisible(true);
      for (final javafx.scene.chart.XYChart.Series<String, Number> series : getData())
      {
         final CheckBox cb = new CheckBox(series.getName());
         cb.setUserData(series);
         cb.setSelected(true);
         cb.addEventHandler(ActionEvent.ACTION, e ->
         {
            final CheckBox box = (CheckBox) e.getSource();
            @SuppressWarnings("unchecked")
            final Series<String, Number> s = (Series<String, Number>) box.getUserData();
            s.getNode().setVisible(box.isSelected());
         });
         legend.getChildren().add(cb);
      }
      setLegend(legend);
   }
}

I'll leave it as an exercise for the reader to make the legend more readable, for example, borders around each checkbox and binding the color of the series to the something showing that color in the checkbox for the series.

One other thing, you might want to check the getLegendSide() method to decide which kind of layout container to use for the legend, i.e. HBox for TOP and BOTTOM but VBOX for LEFT and RIGHT. Your choice.

like image 36
Two Trucks Avatar answered Sep 26 '22 03:09

Two Trucks