JavaFX BarChart,按系列名称设置系列颜色

ker*_*000 3 javafx

我正在尝试动态设置BarChart Series颜色。

我希望同一个系列名称始终具有相同的颜色。 它在图表中并不总是相同的系列名称,这就是为什么我不能依赖图表中的位置(默认颜色在数据列表中的相同位置总是相同的)。

chart.getData().addListener(new ListChangeListener<Series<String, Number>>() {

        @Override
        public void onChanged(
            final javafx.collections.ListChangeListener.Change<? extends Series<String, Number>> c) {
        while (c.next()) {
            for (final Series s : c.getAddedSubList()) {
            if ("booking".equalsIgnoreCase(s.getName())) {
                if (s.getNode() != null) {
                s.getNode().getStyleClass().add(".source-background-booking");
                }
            } else if ("airbnb".equalsIgnoreCase(s.getName())) {
                if (s.getNode() != null) {
                s.getNode().getStyleClass().add(".source-background-airbnb");
                }
            }
            }
        }
        }
    });
Run Code Online (Sandbox Code Playgroud)

这不会按预期工作。该SeriesNode始终null。这是为什么?

编辑:另一种不起作用的方法:

chart.getData().addListener(new ListChangeListener<Series<String, Number>>() {

        @Override
        public void onChanged(
            final javafx.collections.ListChangeListener.Change<? extends Series<String, Number>> c) {
        while (c.next()) {
            System.err.println("Series " + c.getAddedSubList() + " kommt rein..");
            for (final Series<String, Number> s : c.getAddedSubList()) {
            s.nodeProperty().addListener(new ChangeListener<Node>() {

                @Override
                public void changed(final ObservableValue<? extends Node> observable, final Node oldValue,
                    final Node newValue) {
                System.err.println("Already good");
                if ("booking".equalsIgnoreCase(s.getName())) {
                    newValue.getStyleClass().add(".source-background-booking");
                    System.err.println("Seems to work..");
                } else if ("airbnb".equalsIgnoreCase(s.getName())) {
                    newValue.getStyleClass().add(".source-background-airbnb");
                    System.err.println("Seems to work..");
                }
                }
            });

            }
        }
        }
    });
Run Code Online (Sandbox Code Playgroud)

不幸的是,这个回调似乎从未被调用过..

Sed*_*ick 5

尝试这个:

import com.sun.javafx.charts.Legend;
import com.sun.javafx.charts.Legend.LegendItem;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.chart.XYChart.Data;
import javafx.scene.chart.XYChart.Series;
import javafx.scene.control.Label;
import javafx.stage.Stage;

public class BarChartSample extends Application {
    final static String austria = "Austria";
    final static String brazil = "Brazil";
    final static String france = "France";
    final static String italy = "Italy";
    final static String usa = "USA";

    @Override public void start(Stage stage) {
        stage.setTitle("Bar Chart Sample");
        final CategoryAxis xAxis = new CategoryAxis();
        final NumberAxis yAxis = new NumberAxis();
        final BarChart<String,Number> bc = new BarChart(xAxis,yAxis);
        bc.setTitle("Country Summary");
        xAxis.setLabel("Country");       
        yAxis.setLabel("Value");

        XYChart.Series series1 = new XYChart.Series();
        series1.setName("2003");       
        series1.getData().add(new XYChart.Data(austria, 25601.34));
        series1.getData().add(new XYChart.Data(brazil, 20148.82));
        series1.getData().add(new XYChart.Data(france, 10000));
        series1.getData().add(new XYChart.Data(italy, 35407.15));
        series1.getData().add(new XYChart.Data(usa, 12000));      

        XYChart.Series series2 = new XYChart.Series();
        series2.setName("2004");
        series2.getData().add(new XYChart.Data(austria, 57401.85));
        series2.getData().add(new XYChart.Data(brazil, 41941.19));
        series2.getData().add(new XYChart.Data(france, 45263.37));
        series2.getData().add(new XYChart.Data(italy, 117320.16));
        series2.getData().add(new XYChart.Data(usa, 14845.27));  

        XYChart.Series series3 = new XYChart.Series();
        series3.setName("2005");
        series3.getData().add(new XYChart.Data(austria, 45000.65));
        series3.getData().add(new XYChart.Data(brazil, 44835.76));
        series3.getData().add(new XYChart.Data(france, 18722.18));
        series3.getData().add(new XYChart.Data(italy, 17557.31));
        series3.getData().add(new XYChart.Data(usa, 92633.68));  

        Scene scene  = new Scene(bc,800,600);
        bc.getData().addAll(series1, series2, series3);
        stage.setScene(scene);
        stage.show();

        //Used to change series color.
        for (XYChart.Series<String, Number> series : bc.getData()) {
            if(series.getName().equals("2003"))
            {
                System.out.println("Series name: " + series.getName());
                for(Data data : series.getData())
                {
                    data.getNode().setStyle("-fx-bar-fill: firebrick;");
                }                        
            }                    
        }

        //Used to change legend color
        for(Node n : bc.getChildrenUnmodifiable())
        {
            if(n instanceof Legend)
            {
                System.out.println(((Legend)n).getItems());
                for(LegendItem items : ((Legend)n).getItems())
                {
                    System.out.println("Legend item text: " + items.getText());
                    if(items.getText().equals("2003"))
                    {
                        items.getSymbol().setStyle("-fx-bar-fill: firebrick;");
                    }
                }
            }
        }

    }

    public static void main(String[] args) {
        launch(args);
    }

}
Run Code Online (Sandbox Code Playgroud)

对于 Java 10 及更高版本,将Used to change legend color代码替换为以下代码。未在 Java 9 上测试

//Used to change legend color
for(Node node : bc.lookupAll("Label.chart-legend-item"))
{
    Label tempLabel = (Label)node;
    if(tempLabel.getText().equals("2003"))
    {
        tempLabel.getGraphic().setStyle("-fx-bar-fill: firebrick;");
    }           
}
Run Code Online (Sandbox Code Playgroud)

此应用程序将 2003 系列颜色更改为耐火砖。for 循环是您应该关注的部分。

更新 我添加了一种更改图例颜色的方法。

更新 08/08/2019 原始代码适用于 Java 8。我正在为 Java 10 及更高版本添加代码。