Che*_*ple 7 javafx pie-chart donut-chart
我在离线环境中工作,因此无法复制整个代码库,我将尽我所能描述。
JavaFX不提供甜甜圈图,因此我通过简单地扩展PieChart然后在中心添加一个圆圈来创建了自定义甜甜圈图。伪代码如下所示:
public class DonutChart extends PieChart{
private final Circle innerCircle;
//Initialize PieChart
//Override "layoutChartChildren()" method to override chart label with value instead of name
//Calculate chart bounds by looping through each node to find the max/min X/Y bounds.
//Create a smaller circle and relocate it to the center of the PieChart
}
Run Code Online (Sandbox Code Playgroud)
这给了我想要的甜甜圈图,但是现在我希望有一个双甜甜圈图,这意味着可以进一步细分图表。我再次做了同样的事情,但是这次,我不仅添加了“ innerCircle”,还添加了另一个饼图。现在看起来像这样:
public class DonutChart extends PieChart{
private final Circle innerCircle;
private PieChart innerChart;
/*
* Initialize PieChart
* Override "layoutChartChildren()" method to override chart label with value instead of name
* Calculate chart bounds by looping through each node to find the max/min X/Y bounds.
* Create and add innerChart and innerCircle
*/
private void addChartAndCircle(){
if (getData().size > 0){
Node pie = getData().get(0).getNode();
if (pie.getParent() instanceof Pane){
Pane parent = pie.getParent();
if (!parent.getChildren().contains(innerChart)){
parent.getChildren().add(innerChart);
}
if (!parent.getChildren().contains(innerCircle)){
parent.getChildren().add(innerCircle);
}
}
}
}
//Relocate to center
}
Run Code Online (Sandbox Code Playgroud)
仅显示外部图表“ DonutChart”和内部圆圈,但看不到innerChart。我还观察到内部图表的width属性为0,并且我尝试绑定该属性,将innerChart的max / min / pref width / height设置为无效,但无济于事。
有谁能够创建显示两层的自定义甜甜圈图?
由于这个问题看起来很有趣,因此我尝试了您的要求。确实,我也遇到了渲染内部图表的确切问题。经过进一步调查,看起来问题出在区域的子布局中。
现在,我们正在介绍一个陌生人(又名内部图表),外部图表的layoutChildren()不知道如何呈现它。您可能会问,圆是如何渲染的。我认为Shapes的工作方式会有所不同。不确定 ;-)
因此,要使其工作,您需要在外部图表的layoutChartChildren()方法中提供内部图表的大小。
跳过一些您提供的内容,下面是我尝试使其工作的快速演示。希望对您有所帮助。
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.BoundingBox;
import javafx.geometry.Bounds;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.PieChart;
import javafx.scene.layout.Pane;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import java.util.Set;
import java.util.stream.Collectors;
public class PieChartSample extends Application {
@Override
public void start(Stage stage) {
Scene scene = new Scene(new Group());
stage.setTitle("Imported Fruits");
stage.setWidth(500);
stage.setHeight(500);
ObservableList<PieChart.Data> pieChartData =
FXCollections.observableArrayList(
new PieChart.Data("Grapefruit", 45),
new PieChart.Data("Oranges", 25),
new PieChart.Data("Plums", 30));
ObservableList<PieChart.Data> innerChartData =
FXCollections.observableArrayList(
new PieChart.Data("G1", 20),
new PieChart.Data("G2", 25),
new PieChart.Data("O1", 10),
new PieChart.Data("O2", 15),
new PieChart.Data("P1", 15),
new PieChart.Data("P2", 15));
final DonutChart chart = new DonutChart(pieChartData);
chart.setTitle("Imported Fruits");
chart.setInnerChartData(innerChartData);
((Group) scene.getRoot()).getChildren().add(chart);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(args);
}
class DonutChart extends PieChart {
private final double SPACE = 30; /* Gap between outer and inner pie*/
private PieChart innerChart;
private Circle circle;
private Bounds outerPieBounds;
public DonutChart(ObservableList<PieChart.Data> data) {
super(data);
innerChart = new PieChart() {
@Override
protected void layoutChartChildren(double top, double left, double contentWidth, double contentHeight) {
super.layoutChartChildren(top, left, contentWidth, contentHeight);
final Pane chartContent = (Pane) lookup(".chart-content");
chartContent.setPadding(new Insets(0));
}
};
innerChart.setPadding(new Insets(0));
innerChart.setLabelsVisible(false);
innerChart.setLegendVisible(false);
circle = new Circle(40);
circle.setOpacity(1);
circle.setStyle("-fx-fill:white;");
}
@Override
protected void layoutChartChildren(double top, double left, double contentWidth, double contentHeight) {
super.layoutChartChildren(top, left, contentWidth, contentHeight);
final Pane chartContent = (Pane) lookup(".chart-content");
if (!chartContent.getChildren().contains(innerChart)) {
chartContent.getChildren().add(innerChart);
}
if (!chartContent.getChildren().contains(circle)) {
chartContent.getChildren().add(circle);
}
updateOuterPieBounds();
double cX = outerPieBounds.getMinX() + (outerPieBounds.getWidth() / 2);
double cY = outerPieBounds.getMinY() + (outerPieBounds.getHeight() / 2);
circle.setCenterX(cX);
circle.setCenterY(cY);
double innerSize = outerPieBounds.getWidth() - (2 * SPACE);
innerChart.resize(innerSize, innerSize); // THIS WHERE YOUR ISSUE LIES. YOU NEED TO PROVIDE THE SIZE TO INNER CHART
innerChart.setTranslateX(cX - innerChart.getWidth() / 2);
innerChart.setTranslateY(cY - innerChart.getHeight() / 2);
}
public void setInnerChartData(ObservableList<PieChart.Data> data) {
innerChart.setData(data);
}
/**
* Determining the outer pie visual bounds.
*/
private void updateOuterPieBounds() {
Pane chartContent = (Pane) lookup(".chart-content");
Set<Node> pieNodes = chartContent.getChildren().stream().filter(node -> node.getStyleClass().contains("chart-pie")).collect(Collectors.toSet());
double minX = getWidth();
double minY = getHeight();
double maxX = 0, maxY = 0;
for (Node pie : pieNodes) {
Bounds pieBounds = pie.getBoundsInParent();
minX = Math.min(minX, pieBounds.getMinX());
minY = Math.min(minY, pieBounds.getMinY());
maxX = Math.max(maxX, pieBounds.getMaxX());
maxY = Math.max(maxY, pieBounds.getMaxY());
}
outerPieBounds = new BoundingBox(minX, minY, maxX - minX, maxY - minY);
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
91 次 |
| 最近记录: |