Удалить Элементы Легенды LineChart JavaFX 2
У меня есть таблица с множеством серий. Эти серии сгруппированы в одну или несколько суперсерий. Каждый супер-ряд может иметь много "разрывов" в строке, чтобы точно изобразить, когда процесс монитора не активно собирает данные. Каждый перерыв данных фактически запускает новую серию.
мне удалось успешно преодолеть несколько технических проблем, таких как диаграмма, назначающая новый цвет каждой новой серии, цвет символа линии диаграммы, не соответствующий серии цвет и т. д. Все работает довольно хорошо, за исключением того, что каждый раз, когда я добавляю новую серию в диаграмму, она добавляет элемент в легенду.
есть ли способ удалить элементы из легенды, или мне нужно скрыть легенду по умолчанию и добавить свою собственную панель легенд?
3 ответов
chart.setLegendVisible(false);
затем вы можете создать свою собственную панель, чтобы создать свою собственную легенду и отобразить ее так, как вы хотите.
после нескольких неудачных попыток реализации различных предложений я обнаружил, что лучший способ позволить пользователю показать/скрыть ряд данных в диаграмме JavaFx (или ее подклассах)-расширить класс диаграммы, который вы хотите использовать, и переопределить его метод updateLegend ().
Это довольно просто на самом деле. Вот пример использования базового HBox в качестве легенды, содержащей флажки в качестве элементов легенды. В этом примере я решил сделать свой LineChart с фиксированными типами осей (CategoryAxis и NumberAxis). Вы можете оставить свой подкласс с дженериками для осей.
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);
}
}
Я оставлю это как упражнение для читателя, чтобы сделать легенду более читаемой, например, границы вокруг каждого флажка и привязку цвета серии К чему-то, показывающему этот цвет в флажке для серии.
еще одна вещь, вы можете проверить метод getLegendSide (), чтобы решить, какой контейнер макета использовать для легенды, т. е. HBox для верхней и нижней, но VBOX для левой и правой. Ваш выбор.
вы можете найти узел на основе его типа (и опционально имя стиля) используя этот метод:
private static Node findNode(final Parent aParent, final String aClassname, final String aStyleName) {
if (null != aParent) {
final ObservableList<Node> children = aParent.getChildrenUnmodifiable();
if (null != children) {
for (final Node child : children) {
String className = child.getClass().getName();
if (className.contains("$")) {
className = className.substring(0, className.indexOf("$"));
}
if (0 == aClassname.compareToIgnoreCase(className)) {
if ((null == aStyleName) || (0 == aStyleName.length())) {
// No aStyleName, just return this:
return child;
}
else {
final String styleName = child.getStyleClass().toString();
if (0 == aStyleName.compareToIgnoreCase(styleName)) {
return child;
}
}
}
if (child instanceof Parent) {
final Node node = findNode((Parent) child, aClassname, aStyleName);
if (null != node) {
return node;
}
}
}
}
}
return null;
}
вызов его с диаграммой в вопросе, чтобы получить узел легенды:
Legend legend = (Legend) findNode(chart, Legend.class.getName(), "chart-legend");
который вы можете затем повторить через детей и удалить те, которые вы не хотите, чтобы отображаться:
for (final Node legendItem : legend.getChildren()) {
final Label legendLabel = (Label) legendItem;
if (0 == legendLabel.getText().compareToIgnoreCase("the name of the legend I want hidden (or replaced with some other test)")) {
legend.getChildren().remove(legendItem);
break;
}
}
JavaFX также имеет lookup
функция, которая " находит этот узел или первый подузел на основе заданного селектора CSS. и действует похожие на findNode
функция из этого ответа.