java javafx charts legend

JavaFX Use Chart Legend para alternar show/hide Series ¿posible?



charts (2)

¿Es posible utilizar la leyenda de un gráfico para alternar mostrar / ocultar una serie?

Tengo un LineChart con una leyenda y hay demasiadas Series por lo que no se puede leer bien la información. Me preguntaba si existe la posibilidad de usar la leyenda para alternar la serie para mostrar / ocultar.

La mayoría de los nombres de mi Series son bastante largos y se ve muy raro si se escriben dos veces una vez en la leyenda para que sepas qué color pertenece a la Series y una segunda vez, además de una CheckBox de CheckBox para alternarlos.

Edit1: Tal vez no estaba claro, incluso si no hay una función incorporada para esto, podría usar algunos comentarios sobre cómo podría ser una nota de audio, porque no puedo encontrar nada.


Como referencia, un enfoque similar funciona con JFreeChart en JavaFX como se muestra aquí . Adaptado de este ejemplo , la variación a continuación agrega un ChartMouseListenerFX al ChartViewer . Haga clic en una serie o en su elemento de leyenda para hacer que una serie sea invisible; haga clic en cualquier otro lugar para restaurarlo.

import javafx.application.Application; import javafx.scene.Scene; import javafx.stage.Stage; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.entity.ChartEntity; import org.jfree.chart.entity.LegendItemEntity; import org.jfree.chart.entity.XYItemEntity; import org.jfree.chart.fx.ChartViewer; import org.jfree.chart.fx.interaction.ChartMouseEventFX; import org.jfree.chart.fx.interaction.ChartMouseListenerFX; import org.jfree.chart.labels.StandardXYToolTipGenerator; import org.jfree.chart.plot.XYPlot; import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; import org.jfree.data.xy.XYSeries; import org.jfree.data.xy.XYSeriesCollection; /** * @see https://.com/a/44967809/230513 * @see https://.com/a/43286042/230513 */ public class VisibleTest extends Application { @Override public void start(Stage stage) { XYSeriesCollection dataset = new XYSeriesCollection(); for (int i = 0; i < 3; i++) { XYSeries series = new XYSeries("value" + i); for (double t = 0; t < 2 * Math.PI; t += 0.5) { series.add(t, Math.sin(t) + i); } dataset.addSeries(series); } NumberAxis xAxis = new NumberAxis("domain"); NumberAxis yAxis = new NumberAxis("range"); XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer(true, true); renderer.setBaseToolTipGenerator(new StandardXYToolTipGenerator()); XYPlot plot = new XYPlot(dataset, xAxis, yAxis, renderer); JFreeChart chart = new JFreeChart("Test", plot); ChartViewer viewer = new ChartViewer(chart); viewer.addChartMouseListener(new ChartMouseListenerFX() { @Override public void chartMouseClicked(ChartMouseEventFX e) { ChartEntity ce = e.getEntity(); if (ce instanceof XYItemEntity) { XYItemEntity item = (XYItemEntity) ce; renderer.setSeriesVisible(item.getSeriesIndex(), false); } else if (ce instanceof LegendItemEntity) { LegendItemEntity item = (LegendItemEntity) ce; Comparable key = item.getSeriesKey(); renderer.setSeriesVisible(dataset.getSeriesIndex(key), false); } else { for (int i = 0; i < dataset.getSeriesCount(); i++) { renderer.setSeriesVisible(i, true); } } } @Override public void chartMouseMoved(ChartMouseEventFX e) {} }); stage.setScene(new Scene(viewer)); stage.setTitle("JFreeChartFX"); stage.setWidth(640); stage.setHeight(480); stage.show(); } public static void main(String[] args) { launch(args); } }


Así es como lo resolví: no conozco ninguna solución integrada más simple

LineChart<Number, Number> chart; for (Node n : chart.getChildrenUnmodifiable()) { if (n instanceof Legend) { Legend l = (Legend) n; for (Legend.LegendItem li : l.getItems()) { for (XYChart.Series<Number, Number> s : chart.getData()) { if (s.getName().equals(li.getText())) { li.getSymbol().setCursor(Cursor.HAND); // Hint user that legend symbol is clickable li.getSymbol().setOnMouseClicked(me -> { if (me.getButton() == MouseButton.PRIMARY) { s.getNode().setVisible(!s.getNode().isVisible()); // Toggle visibility of line for (XYChart.Data<Number, Number> d : s.getData()) { if (d.getNode() != null) { d.getNode().setVisible(s.getNode().isVisible()); // Toggle visibility of every node in the series } } } }); break; } } } } }

Necesita ejecutar este código una vez en su gráfico ( LineChart en este ejemplo, pero probablemente pueda adaptarlo a cualquier otro gráfico). Encuentro el niño Legend , y luego itero sobre todos sus ''artículos. Emparejé el elemento de la leyenda con la serie correcta según el nombre; por mi experiencia siempre coinciden, y no pude encontrar una mejor manera de unirlos. Entonces solo se trata de agregar el controlador de eventos correcto a ese elemento de leyenda específico.