图表:如何关联图表之间的颜色?
Charts: How to correlate colors between charts?
下面是一个例子
- 有两个图表可视化同一组数据
- 虽然数据相同,但它们的顺序不同(在动态发生的 rw 代码中)
目标:
- 在两个图表中用相同的颜色显示相同的数据
默认情况下,按添加数据的顺序应用颜色。找不到任何 api 来更改这些颜色 - 很可能我遗漏了一些明显的东西,它是什么?
import java.util.List;
import java.util.function.Supplier;
import java.util.stream.Collector;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.PieChart;
import javafx.scene.chart.PieChart.Data;
import javafx.scene.chart.StackedBarChart;
import javafx.scene.chart.XYChart;
import javafx.scene.chart.XYChart.Series;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class CorrelatedChartColors extends Application {
@Override
public void start(Stage primaryStage) {
PieChart pieChart = new PieChart();
pieChart.setData(getPieData());
final CategoryAxis xAxis = new CategoryAxis();
final NumberAxis yAxis = new NumberAxis();
final StackedBarChart<String, Number> sbc =
new StackedBarChart<>(xAxis, yAxis);
ObservableList<Series<String, Number>> barData = createBarData(getPieData());
// simulate client code that re-orders/filters the data
FXCollections.shuffle(barData);
sbc.setData(barData);
primaryStage.setTitle("Correlated Charts");
Scene scene = new Scene(new HBox(pieChart, sbc));
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* Creates and returns data for StackedBarChart from the given pieData.
*/
@SuppressWarnings("unchecked")
private ObservableList<Series<String, Number>> createBarData(
ObservableList<Data> pieChartData) {
ObservableList<Series<String, Number>> data = pieChartData.stream()
.map(p -> new XYChart.Data<>("none", (Number) p.getPieValue(), p.getName()))
.map(xy -> new Series<>((String)xy.getExtraValue(),
FXCollections.observableArrayList(xy)))
.collect(toObservableList())
;
return data;
}
/**
* Creates and returns data for PieChart.
*/
private ObservableList<Data> getPieData() {
ObservableList<Data> pieData = FXCollections.observableArrayList();
pieData.addAll(new PieChart.Data("java", 17.56),
new PieChart.Data("C", 17.06),
new PieChart.Data("PHP", 6.0),
new PieChart.Data("(Visual)Basic", 4.76),
new PieChart.Data("Other", 31.37));
return pieData;
}
public static <T> Collector<T, ?, ObservableList<T>> toObservableList() {
return Collector.of((Supplier<ObservableList<T>>) FXCollections::observableArrayList,
List::add,
(left, right) -> {
left.addAll(right);
return left;
});
}
public static void main(String[] args) {
launch(args);
}
}
截图:
成功了,这是代码:
public class CorrelatedChartColors extends Application {
@Override
public void start(Stage primaryStage) {
PieChart pieChart = new PieChart();
pieChart.setData(getPieData());
final CategoryAxis xAxis = new CategoryAxis();
final NumberAxis yAxis = new NumberAxis();
final StackedBarChart<String, Number> sbc =
new StackedBarChart<>(xAxis, yAxis);
xAxis.setCategories(FXCollections.<String> observableArrayList(Arrays.asList("Programming Languages Usage in %")));
XYChart.Series<String, Number> series1 = new XYChart.Series();
XYChart.Series<String, Number> series2 = new XYChart.Series();
XYChart.Series<String, Number> series3 = new XYChart.Series();
XYChart.Series<String, Number> series4 = new XYChart.Series();
XYChart.Series<String, Number> series5 = new XYChart.Series();
series1.setName("Java");
series2.setName("C");
series3.setName("PHP");
series4.setName("(Visual)Basic");
series5.setName("Other");
series1.getData().add(new XYChart.Data("Programming Languages Usage in %", 17.56));
series2.getData().add(new XYChart.Data<>("Programming Languages Usage in %", 17.06));
series3.getData().add(new XYChart.Data<>("Programming Languages Usage in %", 6.0));
series4.getData().add(new XYChart.Data<>("Programming Languages Usage in %", 4.76));
series5.getData().add(new XYChart.Data<>("Programming Languages Usage in %", 31.37));
sbc.getData().addAll(series1, series2, series3, series4, series5);
primaryStage.setTitle("Correlated Charts");
Scene scene = new Scene(new HBox(pieChart, sbc));
scene.getStylesheets().add(CorrelatedChartColors.class.getResource("chartStyles.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* Creates and returns data for StackedBarChart from the given pieData.
*/
@SuppressWarnings("unchecked")
private ObservableList<Series<String, Number>> createBarData(
ObservableList<Data> pieChartData) {
ObservableList<Series<String, Number>> data = pieChartData.stream()
.map(p -> new XYChart.Data<>("none", (Number) p.getPieValue(), p.getName()))
.map(xy -> new Series<>((String)xy.getExtraValue(),
FXCollections.observableArrayList(xy)))
.collect(toObservableList())
;
return data;
}
/**
* Creates and returns data for PieChart.
*/
private ObservableList<Data> getPieData() {
ObservableList<Data> pieData = FXCollections.observableArrayList();
pieData.addAll(new PieChart.Data("java", 17.56),
new PieChart.Data("C", 17.06),
new PieChart.Data("PHP", 6.0),
new PieChart.Data("(Visual)Basic", 4.76),
new PieChart.Data("Other", 31.37));
return pieData;
}
public static <T> Collector<T, ?, ObservableList<T>> toObservableList() {
return Collector.of((Supplier<ObservableList<T>>) FXCollections::observableArrayList,
ObservableList::add,
(left, right) -> {
left.addAll(right);
return left;
});
}
public static void main(String[] args) {
launch(args);
}
}
然后是 CSS 文件的代码:
.default-color3.chart-bar {
-fx-bar-fill: black;
}
.default-color0.chart-pie {
-fx-pie-color: black;
}
现在您可以更改 2 个图表中任何一个中每个条形图的颜色。如果要更改顶部栏的颜色,只需添加一个新的 css 条目
.default-color0.chart-bar {
-fx-bar-fill: green;
}
我刚刚更改了启动方法中的一些内容(我确定还有一些导入)。我认为这不是最好的方法。我会在 user.dir 中制作一个样式表,并在其中用 java-color 等名称写下我的颜色,然后将其用于默认图表颜色。
@Override
public void start(Stage primaryStage) {
PieChart pieChart = new PieChart();
pieChart.setData(getPieData());
final HashMap<String, Integer> colors = new HashMap<>();
pieChart.getData().stream().forEach((pd)->{
colors.put(pd.getName(), pieChart.getData().indexOf(pd));
});
final CategoryAxis xAxis = new CategoryAxis(FXCollections.observableArrayList("none"));
final NumberAxis yAxis = new NumberAxis();
final StackedBarChart<String, Number> sbc =
new StackedBarChart<>(xAxis, yAxis);
ObservableList<Series<String, Number>> barData = createBarData(getPieData());
// simulate client code that re-orders/filters the data
FXCollections.shuffle(barData);
sbc.setData(barData);
primaryStage.setTitle("Correlated Charts");
Scene scene = new Scene(new HBox(pieChart, sbc));
primaryStage.setScene(scene);
primaryStage.show();
//can only get nodes after charts are drawn
barData.stream().forEach((bd)->{
int num = colors.get(bd.getName());
//eg. chart-bar series1 data0 default-color1
bd.getData().get(0).getNode().getStyleClass().setAll("chart-bar","series"+num,"data0","default-color"+num);
});
Legend legend = (Legend)sbc.lookup(".chart-legend");
legend.getChildrenUnmodifiable().stream().forEach((l)->{
Label label = (Label)l;
Node n = label.getGraphic();
int num = colors.get(label.getText());
//eg. chart-legend-item-symbol chart-bar series1 bar-legend-symbol default-color1
n.getStyleClass().setAll("chart-legend-item-symbol","chart-bar","series"+num,"bar-legend-symbol","default-color"+num);
});
}
下面是一个例子
- 有两个图表可视化同一组数据
- 虽然数据相同,但它们的顺序不同(在动态发生的 rw 代码中)
目标:
- 在两个图表中用相同的颜色显示相同的数据
默认情况下,按添加数据的顺序应用颜色。找不到任何 api 来更改这些颜色 - 很可能我遗漏了一些明显的东西,它是什么?
import java.util.List;
import java.util.function.Supplier;
import java.util.stream.Collector;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.chart.CategoryAxis;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.PieChart;
import javafx.scene.chart.PieChart.Data;
import javafx.scene.chart.StackedBarChart;
import javafx.scene.chart.XYChart;
import javafx.scene.chart.XYChart.Series;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class CorrelatedChartColors extends Application {
@Override
public void start(Stage primaryStage) {
PieChart pieChart = new PieChart();
pieChart.setData(getPieData());
final CategoryAxis xAxis = new CategoryAxis();
final NumberAxis yAxis = new NumberAxis();
final StackedBarChart<String, Number> sbc =
new StackedBarChart<>(xAxis, yAxis);
ObservableList<Series<String, Number>> barData = createBarData(getPieData());
// simulate client code that re-orders/filters the data
FXCollections.shuffle(barData);
sbc.setData(barData);
primaryStage.setTitle("Correlated Charts");
Scene scene = new Scene(new HBox(pieChart, sbc));
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* Creates and returns data for StackedBarChart from the given pieData.
*/
@SuppressWarnings("unchecked")
private ObservableList<Series<String, Number>> createBarData(
ObservableList<Data> pieChartData) {
ObservableList<Series<String, Number>> data = pieChartData.stream()
.map(p -> new XYChart.Data<>("none", (Number) p.getPieValue(), p.getName()))
.map(xy -> new Series<>((String)xy.getExtraValue(),
FXCollections.observableArrayList(xy)))
.collect(toObservableList())
;
return data;
}
/**
* Creates and returns data for PieChart.
*/
private ObservableList<Data> getPieData() {
ObservableList<Data> pieData = FXCollections.observableArrayList();
pieData.addAll(new PieChart.Data("java", 17.56),
new PieChart.Data("C", 17.06),
new PieChart.Data("PHP", 6.0),
new PieChart.Data("(Visual)Basic", 4.76),
new PieChart.Data("Other", 31.37));
return pieData;
}
public static <T> Collector<T, ?, ObservableList<T>> toObservableList() {
return Collector.of((Supplier<ObservableList<T>>) FXCollections::observableArrayList,
List::add,
(left, right) -> {
left.addAll(right);
return left;
});
}
public static void main(String[] args) {
launch(args);
}
}
截图:
成功了,这是代码:
public class CorrelatedChartColors extends Application {
@Override
public void start(Stage primaryStage) {
PieChart pieChart = new PieChart();
pieChart.setData(getPieData());
final CategoryAxis xAxis = new CategoryAxis();
final NumberAxis yAxis = new NumberAxis();
final StackedBarChart<String, Number> sbc =
new StackedBarChart<>(xAxis, yAxis);
xAxis.setCategories(FXCollections.<String> observableArrayList(Arrays.asList("Programming Languages Usage in %")));
XYChart.Series<String, Number> series1 = new XYChart.Series();
XYChart.Series<String, Number> series2 = new XYChart.Series();
XYChart.Series<String, Number> series3 = new XYChart.Series();
XYChart.Series<String, Number> series4 = new XYChart.Series();
XYChart.Series<String, Number> series5 = new XYChart.Series();
series1.setName("Java");
series2.setName("C");
series3.setName("PHP");
series4.setName("(Visual)Basic");
series5.setName("Other");
series1.getData().add(new XYChart.Data("Programming Languages Usage in %", 17.56));
series2.getData().add(new XYChart.Data<>("Programming Languages Usage in %", 17.06));
series3.getData().add(new XYChart.Data<>("Programming Languages Usage in %", 6.0));
series4.getData().add(new XYChart.Data<>("Programming Languages Usage in %", 4.76));
series5.getData().add(new XYChart.Data<>("Programming Languages Usage in %", 31.37));
sbc.getData().addAll(series1, series2, series3, series4, series5);
primaryStage.setTitle("Correlated Charts");
Scene scene = new Scene(new HBox(pieChart, sbc));
scene.getStylesheets().add(CorrelatedChartColors.class.getResource("chartStyles.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* Creates and returns data for StackedBarChart from the given pieData.
*/
@SuppressWarnings("unchecked")
private ObservableList<Series<String, Number>> createBarData(
ObservableList<Data> pieChartData) {
ObservableList<Series<String, Number>> data = pieChartData.stream()
.map(p -> new XYChart.Data<>("none", (Number) p.getPieValue(), p.getName()))
.map(xy -> new Series<>((String)xy.getExtraValue(),
FXCollections.observableArrayList(xy)))
.collect(toObservableList())
;
return data;
}
/**
* Creates and returns data for PieChart.
*/
private ObservableList<Data> getPieData() {
ObservableList<Data> pieData = FXCollections.observableArrayList();
pieData.addAll(new PieChart.Data("java", 17.56),
new PieChart.Data("C", 17.06),
new PieChart.Data("PHP", 6.0),
new PieChart.Data("(Visual)Basic", 4.76),
new PieChart.Data("Other", 31.37));
return pieData;
}
public static <T> Collector<T, ?, ObservableList<T>> toObservableList() {
return Collector.of((Supplier<ObservableList<T>>) FXCollections::observableArrayList,
ObservableList::add,
(left, right) -> {
left.addAll(right);
return left;
});
}
public static void main(String[] args) {
launch(args);
}
}
然后是 CSS 文件的代码:
.default-color3.chart-bar {
-fx-bar-fill: black;
}
.default-color0.chart-pie {
-fx-pie-color: black;
}
现在您可以更改 2 个图表中任何一个中每个条形图的颜色。如果要更改顶部栏的颜色,只需添加一个新的 css 条目
.default-color0.chart-bar {
-fx-bar-fill: green;
}
我刚刚更改了启动方法中的一些内容(我确定还有一些导入)。我认为这不是最好的方法。我会在 user.dir 中制作一个样式表,并在其中用 java-color 等名称写下我的颜色,然后将其用于默认图表颜色。
@Override
public void start(Stage primaryStage) {
PieChart pieChart = new PieChart();
pieChart.setData(getPieData());
final HashMap<String, Integer> colors = new HashMap<>();
pieChart.getData().stream().forEach((pd)->{
colors.put(pd.getName(), pieChart.getData().indexOf(pd));
});
final CategoryAxis xAxis = new CategoryAxis(FXCollections.observableArrayList("none"));
final NumberAxis yAxis = new NumberAxis();
final StackedBarChart<String, Number> sbc =
new StackedBarChart<>(xAxis, yAxis);
ObservableList<Series<String, Number>> barData = createBarData(getPieData());
// simulate client code that re-orders/filters the data
FXCollections.shuffle(barData);
sbc.setData(barData);
primaryStage.setTitle("Correlated Charts");
Scene scene = new Scene(new HBox(pieChart, sbc));
primaryStage.setScene(scene);
primaryStage.show();
//can only get nodes after charts are drawn
barData.stream().forEach((bd)->{
int num = colors.get(bd.getName());
//eg. chart-bar series1 data0 default-color1
bd.getData().get(0).getNode().getStyleClass().setAll("chart-bar","series"+num,"data0","default-color"+num);
});
Legend legend = (Legend)sbc.lookup(".chart-legend");
legend.getChildrenUnmodifiable().stream().forEach((l)->{
Label label = (Label)l;
Node n = label.getGraphic();
int num = colors.get(label.getText());
//eg. chart-legend-item-symbol chart-bar series1 bar-legend-symbol default-color1
n.getStyleClass().setAll("chart-legend-item-symbol","chart-bar","series"+num,"bar-legend-symbol","default-color"+num);
});
}