JavaFX 饼图图例颜色更改

3
我需要改变饼图图例中圆的颜色。我不知道如何获取饼图的这个属性。例如,我可以改变标签图例中文本的颜色,我认为这接近解决方案。
它展示了我想要改变的内容:

enter image description here

@FXML
public PieChart chart;
public ObservableList<PieChart.Data> pieChartData = FXCollections.observableArrayList();

public void chartLoad() { 

    pieChartData.clear();
    List<String> colorList = new ArrayList<>();
    for(int i = 0; i < categoryList.getSize(); i++) {
        if(categoryList.getByIndex(i).getValue() > 0) {
            PieChart.Data data = new PieChart.Data(categoryList.getByIndex(i).getName(), 
                categoryList.getByIndex(i).getValue());
            pieChartData.add(data);
            data.getNode().setStyle("-fx-pie-color: " + 
                categoryList.getByIndex(i).getColor().getName());
            colorList.add(categoryList.getByIndex(i).getColor().getName());
        }
    }

    Set<Node> items = chart.lookupAll("Label.chart-legend-item");
    int i = 0;
    for(Node item : items) {
        Label label = (Label) item;
        label.setText("sampleText");
        label.setStyle("-fx-text-fill: " + colorList.get(i)); 
        System.out.println(label.getChildrenUnmodifiable().toString());
        i++;
    }
    chart.setData(pieChartData);
}

谢谢您未来的评论和回答。
1个回答

1
动态分配颜色到图表有点麻烦。如果你有一组固定的颜色,没有预定义从数据到颜色的映射,你可以使用外部样式表,但是做任何其他事情都需要(据我所知)有点技巧。
默认的modena.css样式表定义了八个常量颜色,CHART_COLOR_1CHART_COLOR_8。饼图中的节点,包括“饼片”和图例中的颜色样本,被分配到八个类default-color0default-color7中的一个样式类。每个这些样式类默认都有-fx-pie-color设置为其中一个常量。不幸的是,如果饼图中的数据发生变化,这些从default-colorxCHART_COLOR_y的映射会以一种未记录的方式发生变化。
因此,我能找到的最好方法适用于您的场景:
  • 将新数据添加到图表中
  • 一旦所有数据都添加完毕,对于每个数据,查找已添加到数据节点的样式类
  • 查找具有该样式类的图表中的所有节点(这也将给出图例样本)
  • 更新这些节点的-fx-pie-color以达到所需的颜色

最后一个陷阱是,您需要确保图例已添加到图表中,并且CSS已应用于图表,以便查找有效。

public void chartLoad() { 

    pieChartData.clear();
    List<String> colors = new ArrayList<>();
    for(int i = 0; i < categoryList.getSize(); i++) {
        if(categoryList.getByIndex(i).getValue() > 0) {
            PieChart.Data data = new PieChart.Data(categoryList.getByIndex(i).getName(), 
                categoryList.getByIndex(i).getValue());
            pieChartData.add(data);
            colors.add(categoryList.getByIndex(i).getColor().getName());
        }
    }

    chart.setData(pieChartData);
    chart.requestLayout();
    chart.applyCSS();

    for (int i = 0 ; i < pieChartData.size() ; i++) {
        PieChart.Data d = pieChartData.get(i);
        String colorClass = "" ;
        for (String cls : d.getNode().getStyleClass()) {
            if (cls.startsWith("default-color")) {
                colorClass = cls ;
                break ;
            }
        }
        for (Node n : chart.lookupAll("."+colorClass)) {
            n.setStyle("-fx-pie-color: "+colors.get(i));
        }
    }

}

这是一个关于该方法的快速完整演示:

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.PieChart;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class PieChartTest extends Application {

    private final Random rng = new Random();

    @Override
    public void start(Stage primaryStage) throws Exception {
        PieChart chart = new PieChart();
        Button button = new Button("Generate Data");
        button.setOnAction(e -> updateChart(chart));
        BorderPane root = new BorderPane(chart);
        HBox controls = new HBox(button);
        controls.setAlignment(Pos.CENTER);
        controls.setPadding(new Insets(5));
        root.setTop(controls);

        Scene scene = new Scene(root, 600, 600);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private void updateChart(PieChart chart) {
        chart.getData().clear();
        int numValues = 4 + rng.nextInt(10);

        List<String> colors = new ArrayList<>();
        List<PieChart.Data> data = new ArrayList<>();



        for (int i = 0 ; i < numValues ; i++) {
            colors.add(getRandomColor());
            PieChart.Data d = new PieChart.Data("Item "+i, rng.nextDouble() * 100);
            data.add( d );
            chart.getData().add(d) ;
        }

        chart.requestLayout();
        chart.applyCss();

        for (int i = 0 ; i < data.size() ; i++) {
            String colorClass = "" ;
            for (String cls : data.get(i).getNode().getStyleClass()) {
                if (cls.startsWith("default-color")) {
                    colorClass = cls ;
                    break ;
                }
            }
            for (Node n : chart.lookupAll("."+colorClass)) {
                n.setStyle("-fx-pie-color: "+colors.get(i));
            }
        }
    }

    private String getRandomColor() {
        Color color = Color.hsb(rng.nextDouble() * 360, 1, 1);
        int r = (int) (255 * color.getRed()) ;
        int g = (int) (255 * color.getGreen());
        int b = (int) (255 * color.getBlue()) ;

        return String.format("#%02x%02x%02x", r, g, b) ;
    }


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

这确实有点破解,因此更好的解决方案显然是受欢迎的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接