Below is an example that
- has two charts visualizing the same set of data
- while the data are the same, their sequence differs (in rw code that would happen dynamically)
Goal:
- show the same data with the same colors in both charts
By default, colors are applied by sequence of addition of the data. Can't find any api to change those colors - most probably I'm missing something obvious, what is it?
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);
}
}
Screenshot:
Got it working, here's the code:
and then the code for the CSS file:
Now you can change the color of every bar in either one of the 2 charts. If you want to change the color of the top bar, simply add a new css entry
I just changed some stuff in the start method (plus some imports I'm sure). I don't think this is the best way. I would make a stylesheet in user.dir and write my colors there with names like java-color etc., then use that for the default chart colors.