José José - 3 months ago 66
Java Question

JavaFX LineChart legend style

I want to update the style of LineChart legend, i using setStyle on the nodes with the correspoding series class.

String color = ....
XYChart.Series<Number, Number> series = new XYChart.Series<Number, Number>();
_chart.getData().add(series);

String seriesClass = null;
for(String styleClass : series.getNode().getStyleClass())
{
if(styleClass.startsWith("series"))
{
seriesClass = styleClass;
break;
}
}
if(seriesClass != null)
{
//
// Customize the style.
//
StringBuilder sb = new StringBuilder();
sb.append("-fx-stroke: ");
sb.append(color);
sb.append("; ");
sb.append("-fx-background-color: ");
sb.append(color);
sb.append(", white;");
if(doted)
{
sb.append("-fx-stroke-dash-array: 10 10");
}
_styles.put(seriesClass, sb.toString());
}

java.util.Set<javafx.scene.Node> nodes = _chart.lookupAll("." + seriesClass);
for(javafx.scene.Node n : nodes)
{
n.setStyle(style);
}


The thing is that this just affect the style of the path, the legend style doesn't change. I have printed the chart node children and see that legends are not fully created after add series call returns:

Legend@18e8627[styleClass=chart-legend]
Label@1689c98[styleClass=label chart-legend-item]
Label@100e4ce[styleClass=label chart-legend-item]
Label@1adcb5e[styleClass=label chart-legend-item]
Label@102a8fb[styleClass=label chart-legend-item]


A bit later if i print the children again:

Legend@9a095[styleClass=chart-legend]
Label[id=null, styleClass=label chart-legend-item]
LabelSkin[id=null, styleClass=label chart-legend-item]
Region@12acafc[styleClass=chart-legend-item-symbol chart-line-symbol series0 default-color0]
LabeledText@749a47[styleClass=text]
Label[id=null, styleClass=label chart-legend-item]
LabelSkin[id=null, styleClass=label chart-legend-item]
Region@3ca3a4[styleClass=chart-legend-item-symbol chart-line-symbol series1 default-color1]
LabeledText@11b9972[styleClass=text]
Label[id=null, styleClass=label chart-legend-item]
LabelSkin[id=null, styleClass=label chart-legend-item]
Region@57f433[styleClass=chart-legend-item-symbol chart-line-symbol series2 default-color2]
LabeledText@6172b5[styleClass=text]
Label[id=null, styleClass=label chart-legend-item]
LabelSkin[id=null, styleClass=label chart-legend-item]
Region@16458ed[styleClass=chart-legend-item-symbol chart-line-symbol series3 default-color3]
LabeledText@10a68bd[styleClass=text]


If i update the style now, the legend style update correctly.

How can i know when the Region child with classes needed for set the style were added, so i can setStyle on that nodes?

any other ideas to update the legend style when a new series has been added?

Answer

I ran into this issue as well. Came up with a work-around that detects when the legend items are created so that dynamic styling can be added to them.

I added a ListChangeListener to the legend's "getChildrenUnmodifiable()" ObservableList, which in turn adds a ListChangeListener to each of the legend's children as they get added. From within this listener, we can tell when new items are being added to the legend (or removed). This allow us to then make the dynamic style changes.

for (Node n : lineChart.getChildrenUnmodifiable())
        {
            if (n instanceof Legend)
            {
                final Legend legend = (Legend) n;

                // remove the legend
                legend.getChildrenUnmodifiable().addListener(new ListChangeListener<Object>()
                {
                    @Override
                    public void onChanged(Change<?> arg0)
                    {
                        for (Node node : legend.getChildrenUnmodifiable())
                        {
                            if (node instanceof Label)
                            {
                                final Label label = (Label) node;
                                label.getChildrenUnmodifiable().addListener(new ListChangeListener<Object>()
                                {
                                    @Override
                                    public void onChanged(Change<?> arg0)
                                    {
                                        //make style changes here
                                    }

                                });
                            }
                        }
                    }
                });
            }
        }
Comments