2014-01-07 5 views
5

У меня есть линейная диаграмма со многими сериями. Эти серии сгруппированы в одну или несколько суперсерий. Каждая суперсерия может иметь много «разрывов» в строке, чтобы точно изобразить, когда процесс мониторинга не ведет активный сбор данных. Каждый разрыв данных фактически начинает новую серию.Удалить JavaFX 2 LineChart Legend Items

Я смог успешно преодолеть несколько технических проблем, таких как диаграмма, назначающая новый цвет каждой новой серии, цвет символа линии линии, не соответствующий цвету серии, и т. Д. Все работает довольно хорошо прямо сейчас, кроме что каждый раз, когда я добавляю новую диаграмму в диаграмму, она добавляет элемент к легенде.

Есть ли способ удалить элементы из легенды или мне нужно скрыть легенду по умолчанию и добавить мою собственную панель легенд?

ответ

12

Don't show the legend:

chart.setLegendVisible(false); 

Вы можете создать свои собственные панели, чтобы сделать свою собственную легенду и сделать его, как вы хотите.

+0

Спасибо! Вот чего я боялся. :) – RonSiven

+0

Эй, @jewelsea, Еще один вопрос, если вы не возражаете. Я создал свою собственную панель для отображения моей пользовательской легенды. Он выглядит почти так же, как оригинал. Единственное, с чем я столкнулся, это уменьшить ее ширину, когда есть всего несколько серий. Диаграмма и легенда находятся в VBox в диалоговом окне, а легенда - в StackPane в нижней части VBox.Высота изменяется соответствующим образом. Есть ли у вас больше слов мудрости, которые могут помочь мне? – RonSiven

+0

Да, но задайте новый вопрос и включите в него текущий код в качестве [sscce] (http://sscce.org). – jewelsea

0

Вы можете найти узел, основанный на его тип (и, возможно название стиля), используя этот метод:

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; 
} 

Calling его с графиком в вопросе, чтобы получить узел Легенда:

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 из этого ответа.

+0

Метод getChildren() не доступен для класса Legend. Метод getchildren() защищен в родительском классе и расширен по региону и, следовательно, классу Legend. Более того, мы не можем удалить элементы из legend.getChildrenUnmodifiable() – Kishore

+0

@Kishore Запуск против Java 8.0.25, иерархия классов Legend: Object -> Node -> Parent -> Region -> Pane -> TilePane - -> Легенда. У панели есть общедоступные getChildren. –

+0

@ Kishore кажется, что это было изменение, которое позволило: http://hg.openjdk.java.net/openjfx/8u-dev/rt/rev/9823085ebf0e –

1

После нескольких неудачных попыток реализации различных предложений я обнаружил, что лучший способ разрешить пользователю показывать/скрывать серию данных в диаграмме 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 для TOP и BOTTOM, но VBOX для LEFT и RIGHT. Твой выбор.

Смежные вопросы