JavaFX PieChart 图例颜色变化
JavaFX PieChart Legend Color change
我需要更改 PieChart Legend 中圆圈的颜色。我不知道如何访问 PieChart 的 属性。例如,我可以更改标签 Legend 中文本的颜色,我认为这接近于解决方案。
它显示了我要更改的内容:
@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);
}
感谢您以后的评论和回答。
动态地为图表分配颜色有点麻烦。如果你有一组固定的颜色,没有从数据到颜色的预定义映射,你可以只使用外部样式 sheet,但做任何其他事情都需要(据我所知)一点技巧.
默认 modena.css
样式 sheet 定义八种常量颜色,CHART_COLOR_1
到 CHART_COLOR_8
。饼图中的节点,包括 "pie slices" 和图例中的颜色样本,被分配了一个样式 class 从八个 classes default-color0
到 default-color7
.默认情况下,这些样式 class 中的每一个都将 -fx-pie-color
设置为常量之一。不幸的是,如果饼图中的数据发生变化,这些从 default-colorx
到 CHART_COLOR_y
的映射会以未记录的方式发生变化。
因此,我能找到的最适合您的情况的方法是:
- 将新数据添加到图表
- 添加所有数据后,为每个数据查找添加到数据节点
的样式class
- 查找图表中具有该样式的所有节点class(这也会给出图例样本)
- 将这些节点的
-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);
}
}
这确实有点hack,所以显然欢迎更好的解决方案。
我需要更改 PieChart Legend 中圆圈的颜色。我不知道如何访问 PieChart 的 属性。例如,我可以更改标签 Legend 中文本的颜色,我认为这接近于解决方案。
它显示了我要更改的内容:
@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);
}
感谢您以后的评论和回答。
动态地为图表分配颜色有点麻烦。如果你有一组固定的颜色,没有从数据到颜色的预定义映射,你可以只使用外部样式 sheet,但做任何其他事情都需要(据我所知)一点技巧.
默认 modena.css
样式 sheet 定义八种常量颜色,CHART_COLOR_1
到 CHART_COLOR_8
。饼图中的节点,包括 "pie slices" 和图例中的颜色样本,被分配了一个样式 class 从八个 classes default-color0
到 default-color7
.默认情况下,这些样式 class 中的每一个都将 -fx-pie-color
设置为常量之一。不幸的是,如果饼图中的数据发生变化,这些从 default-colorx
到 CHART_COLOR_y
的映射会以未记录的方式发生变化。
因此,我能找到的最适合您的情况的方法是:
- 将新数据添加到图表
- 添加所有数据后,为每个数据查找添加到数据节点 的样式class
- 查找图表中具有该样式的所有节点class(这也会给出图例样本)
- 将这些节点的
-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);
}
}
这确实有点hack,所以显然欢迎更好的解决方案。