我正在编写一个程序,其中饼图中的按钮单击数据会旋转(10时12点的切片会移动到12-2等)。下面的代码(kinda)可以工作,可以旋转,但是会吃到临时切片并创建整个错误段。这是我第一次尝试JavaFX,但我不确定如何管理它。
private BorderPane layout;
private Scene scene;
ObservableList<PieChart.Data> pieChartData =
FXCollections.observableArrayList(
new PieChart.Data("Post-production age", 424236),
new PieChart.Data("Production age", 1030060),
new PieChart.Data("Production age2", 1030060),
new PieChart.Data("Production age3", 1030060),
new PieChart.Data("Pre-production age", 310319));
PieChart chart = new PieChart(pieChartData);
@Override public void start(Stage stage) {
layout = new BorderPane();
scene = new Scene(layout,720,480);
stage.setTitle("People");
stage.setWidth(500);
stage.setHeight(500);
Button button = new Button();
button.setText("rotate");
layout.setBottom(button);
layout.setCenter(chart);
button.setOnAction(e -> {
rotate();
});
chart.setStartAngle(90);
chart.setTitle("Economical age groups");
stage.setScene(scene);
stage.show();
}
public void rotate(){
ObservableList<PieChart.Data> pieChartDataTemp = pieChartData;
int sizeOne = pieChartDataTemp.size();
PieChart.Data tempData = pieChartDataTemp.get(sizeOne-1);
pieChartDataTemp.add(0,tempData);
if(pieChartDataTemp.size()>sizeOne) pieChartDataTemp.remove(pieChartDataTemp.size()-1 );
PieChart chartTemp = new PieChart(pieChartDataTemp);
layout.setCenter(chartTemp);
chartTemp.setStartAngle(90);
}
这是堆栈跟踪:
Exception in thread "JavaFX Application Thread" java.lang.IllegalArgumentException: Children: duplicate children added: parent = Chart$1@5cfeee33[styleClass=chart-content]
at javafx.graphics/javafx.scene.Parent$3.onProposedChange(Parent.java:558)
at javafx.base/com.sun.javafx.collections.VetoableListDecorator.add(VetoableListDecorator.java:206)
at javafx.controls/javafx.scene.chart.PieChart.dataItemAdded(PieChart.java:417)
at javafx.controls/javafx.scene.chart.PieChart.lambda$new$0(PieChart.java:168)
at javafx.base/com.sun.javafx.collections.ListListenerHelper$SingleChange.fireValueChangedEvent(ListListenerHelper.java:164)
at javafx.base/com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(ListListenerHelper.java:73)
at javafx.base/javafx.collections.ObservableListBase.fireChange(ObservableListBase.java:233)
at javafx.base/javafx.collections.ListChangeBuilder.commit(ListChangeBuilder.java:482)
at javafx.base/javafx.collections.ListChangeBuilder.endChange(ListChangeBuilder.java:541)
at javafx.base/javafx.collections.ObservableListBase.endChange(ObservableListBase.java:205)
at javafx.base/javafx.collections.ModifiableObservableListBase.add(ModifiableObservableListBase.java:155)
at task.Main.rotate(Main.java:54)
at task.Main.lambda$start$0(Main.java:39)
(...and so on)
答案 0 :(得分:4)
添加,删除或更新数据时,JavaFX图表支持动画。但是,启用动画后,nodes used to actually display the data不会从图表中删除,直到动画完成为止-这是无法公开观察到的。这意味着您不能像当前所做的那样仅删除PieChart.Data
然后立即重新添加。如果说的Node
当前仍是所说的Parent
的孩子,尝试这样做会导致将Node
添加到Parent
中。如您所言IllegalArgumentException
,duplicate children are not allowed。
您有以下代码(来自#rotate()
):
ObservableList<PieChart.Data> pieChartDataTemp = pieChartData;
int sizeOne = pieChartDataTemp.size();
PieChart.Data tempData = pieChartDataTemp.get(sizeOne - 1);
pieChartDataTemp.add(0,tempData);
if (pieChartDataTemp.size() > sizeOne) {
pieChartDataTemp.remove(pieChartDataTemp.size() - 1);
}
PieChart chartTemp = new PieChart(pieChartDataTemp);
layout.setCenter(chartTemp);
chartTemp.setStartAngle(90);
pieChartDataTemp
和pieChartData
都引用相同的ObservableList
。因此,当您在tempData
索引处添加0
时,实际上是将元素添加到当前PieChart
,而该元素仍在size() - 1
索引中。我尝试通过交换add
和remove
调用来解决此问题,但这并不能解决问题,这就是我发现动画妨碍了解决方法。
您还将创建一个新的PieChart
并替换旧的ObservableList
。假设我正确理解了您要执行的操作,则没有必要。由于每个PieChart
使用相同的yourPieChart.setAnimated(false);
,因此也会引起问题。
至少有两种解决方案。
一种解决方法是简单地disable animations:
PieChart.Data
PieChart.Data
另一种选择是从旧版本创建新的import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.chart.PieChart;
import javafx.scene.control.Button;
import javafx.scene.control.Separator;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
private ObservableList<PieChart.Data> createChartData() {
return FXCollections.observableArrayList(
new PieChart.Data("Post-production age", 424236),
new PieChart.Data("Production age", 1030060),
new PieChart.Data("Production age2", 1030060),
new PieChart.Data("Production age3", 1030060),
new PieChart.Data("Pre-production age", 310319)
);
}
@Override
public void start(Stage primaryStage) {
PieChart chart = new PieChart(createChartData());
chart.setStartAngle(90.0);
Button rotateBtn = new Button("Rotate");
rotateBtn.setOnAction(event -> {
event.consume();
PieChart.Data removed = chart.getData().remove(chart.getData().size() - 1);
chart.getData().add(0, new PieChart.Data(removed.getName(), removed.getPieValue()));
});
VBox root = new VBox(10, rotateBtn, new Separator(), chart);
root.setAlignment(Pos.CENTER);
root.setPadding(new Insets(20));
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
}
。这是一个示例:
onAction
旋转代码在按钮的rotateBtn.setOnAction(event -> {
event.consume();
PieChart.Data removed = chart.getData().remove(chart.getData().size() - 1);
chart.getData().add(0, new PieChart.Data(removed.getName(), removed.getPieValue()));
});
处理程序中:
PieChart
请注意,我不会再创建一个 <div v-for="parent_index in 7" :key="parent_index" class="flex justify-center">
<div class="square">
<div class="square-content" style="vertical-align:middle;">User {{ parent_index }}</div>
</div>
<div v-for="index in 14" :key="index" class="square bg-success"
@click="changeDayState(dayCode,$event)">
</div>
</div>
。