如何在 JavaFX 饼图中显示值?
How to display values in JavaFX Pie Chart?
我正在显示饼图,代表学位的每个模块中表现不佳和表现不佳的学生。我的代码显示了这个:
output
但是我希望每个切片的值都出现在其中,我不想要任何花哨的 mouselistener 东西只是为了在切片中显示数字。
我的代码如下:
public class PieChartSample extends Application { //TODO make constructor that takes hashmaps as arguments
static Map<String, Integer> studsabove = new HashMap<String, Integer>();
static Map<String, Integer> studsbelow = new HashMap<String, Integer>();
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("My First JavaFX App");
ArrayList<PieChart> pielist = new ArrayList<PieChart>();
for(Entry<String, Integer> mod: studsabove.entrySet()){
for(Entry<String, Integer> mod2: studsbelow.entrySet()){
PieChart pieChart = new PieChart();
PieChart.Data above = new PieChart.Data(mod.getKey(), mod.getValue());
PieChart.Data below = new PieChart.Data(mod2.getKey(), mod2.getValue());
pieChart.getData().add(above);
pieChart.getData().add(below);
pielist.add(pieChart);
}
}
VBox vbox = new VBox();
for (PieChart pie: pielist){
pie.setLabelLineLength(10); //FIXME
pie.setLegendSide(Side.LEFT);
vbox.getChildren().add(pie);
}
Scene scene = new Scene(vbox, 400, 200); //TODO: Make pie charts appear horizontally rather than vertically
primaryStage.setScene(scene);
primaryStage.setHeight(900);
primaryStage.setWidth(400);
primaryStage.show();
}
public static void main(String[] args) { //TODO: need to figure out how to display the values in the slices of the pie charts
PieChartSample.studsabove.put("CE201", 23);
PieChartSample.studsbelow.put("CE201", 67);
PieChartSample.studsabove.put("CE222", 20);
PieChartSample.studsbelow.put("CE222", 80);
PieChartSample.studsabove.put("CE233", 6);
PieChartSample.studsbelow.put("CE233", 94);
PieChartSample.studsabove.put("CE244", 56);
PieChartSample.studsbelow.put("CE244", 44);
Application.launch(args);
}
}
您可以像这样扩展 PieChart
:
import java.util.HashMap;
import java.util.Map;
import javafx.collections.ListChangeListener;
import javafx.scene.chart.PieChart;
import javafx.scene.layout.Region;
import javafx.scene.shape.Arc;
import javafx.scene.text.Text;
public class LabeledPieChart extends PieChart {
private final Map<Data, Text> _labels = new HashMap<>();
public LabeledPieChart() {
super();
this.getData().addListener((ListChangeListener.Change<? extends Data> c) -> {
addLabels();
});
}
@Override
protected void layoutChartChildren(double top, double left, double contentWidth, double contentHeight) {
super.layoutChartChildren(top, left, contentWidth, contentHeight);
double centerX = contentWidth / 2 + left;
double centerY = contentHeight / 2 + top;
layoutLabels(centerX, centerY);
}
private void addLabels() {
for (Text label : _labels.values()) {
this.getChartChildren().remove(label);
}
_labels.clear();
for (Data vData : getData()) {
final Text dataText;
final double yValue = vData.getPieValue();
dataText = new Text(Double.toString(yValue));
_labels.put(vData, dataText);
this.getChartChildren().add(dataText);
}
}
private void layoutLabels(double centerX, double centerY) {
double total = 0.0;
for (Data d : this.getData()) {
total += d.getPieValue();
}
double scale = (total != 0) ? 360 / total : 0;
for (Map.Entry<Data, Text> entry : _labels.entrySet()) {
Data vData = entry.getKey();
Text vText = entry.getValue();
Region vNode = (Region) vData.getNode();
Arc arc = (Arc) vNode.getShape();
double start = arc.getStartAngle();
double size = (isClockwise()) ? (-scale * Math.abs(vData.getPieValue())) : (scale * Math.abs(vData.getPieValue()));
final double angle = normalizeAngle(start + (size / 2));
final double sproutX = calcX(angle, arc.getRadiusX() / 2, centerX);
final double sproutY = calcY(angle, arc.getRadiusY() / 2, centerY);
vText.relocate(
sproutX - vText.getBoundsInLocal().getWidth(),
sproutY - vText.getBoundsInLocal().getHeight());
}
}
private static double normalizeAngle(double angle) {
double a = angle % 360;
if (a <= -180) {
a += 360;
}
if (a > 180) {
a -= 360;
}
return a;
}
private static double calcX(double angle, double radius, double centerX) {
return (double) (centerX + radius * Math.cos(Math.toRadians(-angle)));
}
private static double calcY(double angle, double radius, double centerY) {
return (double) (centerY + radius * Math.sin(Math.toRadians(-angle)));
}
}
这里有一个主要的class供您测试:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.PieChart.Data;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class JavaFXApplication28 extends Application {
@Override
public void start(Stage stage) {
stage.setTitle("Imported Fruits");
stage.setWidth(500);
stage.setHeight(500);
LabeledPieChart chart = new LabeledPieChart();
chart.setTitle("Imported Fruits");
// Add some data
addPieChartData(chart, "Grapefruit", 13);
addPieChartData(chart, "Oranges", 25);
addPieChartData(chart, "Plums", 10);
addPieChartData(chart, "Pears", 22);
addPieChartData(chart, "Apples", 30);
AnchorPane anchor = new AnchorPane();
Scene scene = new Scene(anchor);
anchor.getChildren().add(chart);
AnchorPane.setBottomAnchor(chart, 0.0);
AnchorPane.setTopAnchor(chart, 0.0);
AnchorPane.setLeftAnchor(chart, 0.0);
AnchorPane.setRightAnchor(chart, 0.0);
stage.setScene(scene);
stage.show();
}
public void addPieChartData(LabeledPieChart pChart, String name, double value) {
final Data data = new Data(name, value);
pChart.getData().add(data);
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
我正在显示饼图,代表学位的每个模块中表现不佳和表现不佳的学生。我的代码显示了这个: output
但是我希望每个切片的值都出现在其中,我不想要任何花哨的 mouselistener 东西只是为了在切片中显示数字。
我的代码如下:
public class PieChartSample extends Application { //TODO make constructor that takes hashmaps as arguments
static Map<String, Integer> studsabove = new HashMap<String, Integer>();
static Map<String, Integer> studsbelow = new HashMap<String, Integer>();
@Override
public void start(Stage primaryStage) throws Exception {
primaryStage.setTitle("My First JavaFX App");
ArrayList<PieChart> pielist = new ArrayList<PieChart>();
for(Entry<String, Integer> mod: studsabove.entrySet()){
for(Entry<String, Integer> mod2: studsbelow.entrySet()){
PieChart pieChart = new PieChart();
PieChart.Data above = new PieChart.Data(mod.getKey(), mod.getValue());
PieChart.Data below = new PieChart.Data(mod2.getKey(), mod2.getValue());
pieChart.getData().add(above);
pieChart.getData().add(below);
pielist.add(pieChart);
}
}
VBox vbox = new VBox();
for (PieChart pie: pielist){
pie.setLabelLineLength(10); //FIXME
pie.setLegendSide(Side.LEFT);
vbox.getChildren().add(pie);
}
Scene scene = new Scene(vbox, 400, 200); //TODO: Make pie charts appear horizontally rather than vertically
primaryStage.setScene(scene);
primaryStage.setHeight(900);
primaryStage.setWidth(400);
primaryStage.show();
}
public static void main(String[] args) { //TODO: need to figure out how to display the values in the slices of the pie charts
PieChartSample.studsabove.put("CE201", 23);
PieChartSample.studsbelow.put("CE201", 67);
PieChartSample.studsabove.put("CE222", 20);
PieChartSample.studsbelow.put("CE222", 80);
PieChartSample.studsabove.put("CE233", 6);
PieChartSample.studsbelow.put("CE233", 94);
PieChartSample.studsabove.put("CE244", 56);
PieChartSample.studsbelow.put("CE244", 44);
Application.launch(args);
}
}
您可以像这样扩展 PieChart
:
import java.util.HashMap;
import java.util.Map;
import javafx.collections.ListChangeListener;
import javafx.scene.chart.PieChart;
import javafx.scene.layout.Region;
import javafx.scene.shape.Arc;
import javafx.scene.text.Text;
public class LabeledPieChart extends PieChart {
private final Map<Data, Text> _labels = new HashMap<>();
public LabeledPieChart() {
super();
this.getData().addListener((ListChangeListener.Change<? extends Data> c) -> {
addLabels();
});
}
@Override
protected void layoutChartChildren(double top, double left, double contentWidth, double contentHeight) {
super.layoutChartChildren(top, left, contentWidth, contentHeight);
double centerX = contentWidth / 2 + left;
double centerY = contentHeight / 2 + top;
layoutLabels(centerX, centerY);
}
private void addLabels() {
for (Text label : _labels.values()) {
this.getChartChildren().remove(label);
}
_labels.clear();
for (Data vData : getData()) {
final Text dataText;
final double yValue = vData.getPieValue();
dataText = new Text(Double.toString(yValue));
_labels.put(vData, dataText);
this.getChartChildren().add(dataText);
}
}
private void layoutLabels(double centerX, double centerY) {
double total = 0.0;
for (Data d : this.getData()) {
total += d.getPieValue();
}
double scale = (total != 0) ? 360 / total : 0;
for (Map.Entry<Data, Text> entry : _labels.entrySet()) {
Data vData = entry.getKey();
Text vText = entry.getValue();
Region vNode = (Region) vData.getNode();
Arc arc = (Arc) vNode.getShape();
double start = arc.getStartAngle();
double size = (isClockwise()) ? (-scale * Math.abs(vData.getPieValue())) : (scale * Math.abs(vData.getPieValue()));
final double angle = normalizeAngle(start + (size / 2));
final double sproutX = calcX(angle, arc.getRadiusX() / 2, centerX);
final double sproutY = calcY(angle, arc.getRadiusY() / 2, centerY);
vText.relocate(
sproutX - vText.getBoundsInLocal().getWidth(),
sproutY - vText.getBoundsInLocal().getHeight());
}
}
private static double normalizeAngle(double angle) {
double a = angle % 360;
if (a <= -180) {
a += 360;
}
if (a > 180) {
a -= 360;
}
return a;
}
private static double calcX(double angle, double radius, double centerX) {
return (double) (centerX + radius * Math.cos(Math.toRadians(-angle)));
}
private static double calcY(double angle, double radius, double centerY) {
return (double) (centerY + radius * Math.sin(Math.toRadians(-angle)));
}
}
这里有一个主要的class供您测试:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.chart.PieChart.Data;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;
public class JavaFXApplication28 extends Application {
@Override
public void start(Stage stage) {
stage.setTitle("Imported Fruits");
stage.setWidth(500);
stage.setHeight(500);
LabeledPieChart chart = new LabeledPieChart();
chart.setTitle("Imported Fruits");
// Add some data
addPieChartData(chart, "Grapefruit", 13);
addPieChartData(chart, "Oranges", 25);
addPieChartData(chart, "Plums", 10);
addPieChartData(chart, "Pears", 22);
addPieChartData(chart, "Apples", 30);
AnchorPane anchor = new AnchorPane();
Scene scene = new Scene(anchor);
anchor.getChildren().add(chart);
AnchorPane.setBottomAnchor(chart, 0.0);
AnchorPane.setTopAnchor(chart, 0.0);
AnchorPane.setLeftAnchor(chart, 0.0);
AnchorPane.setRightAnchor(chart, 0.0);
stage.setScene(scene);
stage.show();
}
public void addPieChartData(LabeledPieChart pChart, String name, double value) {
final Data data = new Data(name, value);
pChart.getData().add(data);
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}