更新饼图中的值 [英] Update values in Pie Chart
问题描述
我正在使用饼图来处理这个例子。我想动态创建数据并在每次生成新的自定义对象时更新饼图:
I'm working on this example with Pie chart. I want to create data dynamically and update Pie chart every time when new custom object is generated:
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.chart.PieChart;
import javafx.scene.chart.PieChart.Data;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.Label;
import javafx.scene.control.MenuItem;
import javafx.scene.control.Tooltip;
import javafx.scene.effect.Glow;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class MainApp extends Application
{
Stage stage;
private ObservableList<Data> pieChartdData = FXCollections.observableArrayList();
private final PieChart chart = new PieChart(pieChartdData);
Label caption;
@Override
public void start(Stage stage)
{
this.stage = stage;
setUserAgentStylesheet(STYLESHEET_MODENA);
Scene scene = new Scene(new Group());
stage.setTitle("Imported Fruits");
stage.setWidth(500);
stage.setHeight(500);
chart.setTitle("Imported Fruits");
// Add some data
addPieChartData("Grapefruit", 13);
addPieChartData("Oranges", 25);
addPieChartData("Plums", 10);
addPieChartData("Pears", 22);
addPieChartData("Apples", 30);
// Some task which updates the Pie Chart
final Task task;
task = new Task<Void>()
{
@Override
protected Void call() throws Exception
{
int max = 50;
int l = 0;
for (int i = 1; i <= max; i++)
{
FSPartitions data1 = FSPartitions.newInstance().FSName("test1").FSType("test1").isReadonly(true).totalSize(3434).usedSize(333).availableSize(3644);
FSPartitions data2 = FSPartitions.newInstance().FSName("test2").FSType("test2").isReadonly(true).totalSize(34334).usedSize(343).availableSize(3544);
FSPartitions data3 = FSPartitions.newInstance().FSName("test3").FSType("test3").isReadonly(true).totalSize(34543).usedSize(353).availableSize(3446);
List<FSPartitions> ss = new ArrayList<>();
ss.add(data1);
ss.add(data2);
ss.add(data3);
updatePieChart(ss);
Thread.sleep(600);
}
return null;
}
};
new Thread(task).start();
((Group) scene.getRoot()).getChildren().addAll(chart, caption);
stage.setScene(scene);
stage.show();
}
public void addPieChartData(String name, double value)
{
pieChartdData.add(new Data(name, value));
caption = new Label();
caption.setTextFill(Color.DARKORANGE);
caption.setStyle("-fx-font: 24 arial;");
for (final Data data : chart.getData())
{
Node node = data.getNode();
node.addEventHandler(MouseEvent.MOUSE_MOVED, new EventHandler<MouseEvent>()
{
@Override
public void handle(MouseEvent e)
{
caption.setTranslateX(e.getSceneX() + 15);
caption.setTranslateY(e.getSceneY());
caption.setText(String.valueOf(data.getPieValue()) + "%");
caption.setVisible(true);
node.setEffect(new Glow());
//String styleString = "-fx-border-color: white; -fx-border-width: 1; -fx-border-style: dashed;";
//node.setStyle(styleString);
}
});
node.addEventHandler(MouseEvent.MOUSE_EXITED, new EventHandler<MouseEvent>()
{
@Override
public void handle(MouseEvent e)
{
caption.setVisible(false);
node.setEffect(null);
//node.setStyle("");
}
});
final MenuItem resizeItem = new MenuItem("Resize");
resizeItem.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent event)
{
System.out.println("Resize requested");
}
});
final MenuItem aboutItem = new MenuItem("About");
aboutItem.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent event)
{
System.out.println("About requested");
}
});
final MenuItem changeColorItem = new MenuItem("Change Color");
changeColorItem.setOnAction(new EventHandler<ActionEvent>()
{
@Override
public void handle(ActionEvent event)
{
System.out.println("change Color Item requested");
}
});
final ContextMenu menu = new ContextMenu(resizeItem, aboutItem, changeColorItem);
node.setOnMouseClicked(new EventHandler<MouseEvent>()
{
@Override
public void handle(MouseEvent event)
{
if (MouseButton.SECONDARY.equals(event.getButton()))
{
menu.show(stage, event.getScreenX(), event.getScreenY());
}
}
});
}
}
// updates existing Data-Object if name matches
public void updatePieChart(List<FSPartitions> obj)
{
for (FSPartitions obj1 : obj)
{
String fsName = obj1.getFSName();
double usedSize = obj1.getUsedSize();
for (Data d : pieChartdData)
{
if (d.getName().equals(fsName))
{
d.setPieValue(usedSize);
return;
}
}
}
pieChartdData.forEach(data
-> data.nameProperty().bind(
Bindings.concat(
data.getName(), " ", data.pieValueProperty(), " Tons"
)
)
);
for (FSPartitions obj1 : obj)
{
String fsName = obj1.getFSName();
double usedSize = obj1.getUsedSize();
pieChartdData.add(new Data(fsName, usedSize));
}
chart.getData().stream().forEach(data ->
{
Tooltip aaas = new Tooltip();
aaas.setText(data.getPieValue() + "%");
Tooltip.install(chart, aaas);
data.pieValueProperty().addListener((observable, oldValue, newValue)
-> aaas.setText(newValue + "%"));
});
chart.setData(pieChartdData);
}
public static void main(String[] args)
{
launch(args);
}
}
class FSPartitions implements Serializable
{
private static final long serialVersionUID = 1L;
private String FSName;
private String FSType;
private boolean isReadonly;
private long totalSize;
private long usedSize;
private long availableSize;
public static FSPartitions newInstance()
{
return new FSPartitions();
}
public FSPartitions()
{
}
@Override
public String toString()
{
return "FSName=" + FSName + ", FSType=" + FSType + ", totalSize=" + totalSize + ", usedSize=" + usedSize + ", availableSize=" + availableSize;
}
public FSPartitions FSName(String FSName)
{
this.FSName = FSName;
return this;
}
public FSPartitions FSType(String FSType)
{
this.FSType = FSType;
return this;
}
public FSPartitions isReadonly(boolean isReadonly)
{
this.isReadonly = isReadonly;
return this;
}
public FSPartitions totalSize(long totalSize)
{
this.totalSize = totalSize;
return this;
}
public FSPartitions usedSize(long usedSize)
{
this.usedSize = usedSize;
return this;
}
public FSPartitions availableSize(long availableSize)
{
this.availableSize = availableSize;
return this;
}
public String getFSName()
{
return FSName;
}
public String getFSType()
{
return FSType;
}
public boolean getIsReadonly()
{
return isReadonly;
}
public long getTotalSize()
{
return totalSize;
}
public long getUsedSize()
{
return usedSize;
}
public long getAvailableSize()
{
return availableSize;
}
}
我还想为饼图添加一些额外的标签切片。看起来我需要完全重新设计代码,因为每次我将拥有不同的数据,我需要可视化数据。我怎么能这个?你能帮我实现这个吗?
I also want to add some additional labels for pie chart slice. Looks like I need to totally redesign the code because every time I will have different data and I need to to visualize the data. How I can to this? Can you help me to implement this?
推荐答案
您可以覆盖 PieChart#layoutChartChildren
以显示其他值饼图切片的标签。我修改了你的代码来展示一个例子。为了添加值,我使用了您的更新线程,但使用变量l修改了 usedSize
值,以在动画中生成更改值和标签。
You can override PieChart#layoutChartChildren
to display additional values in the label of the pie chart slices. I modified your code to show an example. For adding values, I used your update thread, but modified the usedSize
values with the variable "l" to produce changing values and labels in the animation.
以下示例中缺少FSPartitions类。
The FSPartitions class is missing in the below example.
public class MainApp extends Application {
Stage stage;
private ObservableList<Data> pieChartData = FXCollections.observableArrayList();
private final PieChart chart = new PieChart(pieChartData) {
@Override
protected void layoutChartChildren(double top, double left, double contentWidth, double contentHeight) {
if (getLabelsVisible()) {
getData().forEach(d -> {
Optional<Node> opTextNode = chart.lookupAll(".chart-pie-label").stream().filter(n -> n instanceof Text && ((Text) n).getText().contains(d.getName())).findAny();
if (opTextNode.isPresent()) {
((Text) opTextNode.get()).setText(d.getName() + " " + d.getPieValue());
}
});
}
super.layoutChartChildren(top, left, contentWidth, contentHeight);
}};
Label caption = new Label();
@Override
public void start(Stage stage) {
this.stage = stage;
setUserAgentStylesheet(STYLESHEET_MODENA);
Scene scene = new Scene(new Group());
stage.setTitle("File System");
stage.setWidth(500);
stage.setHeight(500);
chart.setTitle("File System Size");
// Some task which updates the Pie Chart
final Task<Void> task = new Task<Void>() {
@Override
protected Void call() throws Exception {
int max = 50;
int l = 0;
for (int i = 1; i <= max; i++) {
FSPartitions data1 = FSPartitions.newInstance().FSName("test1").FSType("test1").isReadonly(true).totalSize(3434).usedSize(333+l).availableSize(3644);
FSPartitions data2 = FSPartitions.newInstance().FSName("test2").FSType("test2").isReadonly(true).totalSize(34334).usedSize(343+(2*l)).availableSize(3544);
FSPartitions data3 = FSPartitions.newInstance().FSName("test3").FSType("test3").isReadonly(true).totalSize(34543).usedSize(353+3*l).availableSize(3446);
l++;
List<FSPartitions> ss = new ArrayList<>();
ss.add(data1);
ss.add(data2);
ss.add(data3);
updatePieChart(ss);
Thread.sleep(600);
}
return null;
}
};
new Thread(task).start();
((Group) scene.getRoot()).getChildren().addAll(chart, caption);
stage.setScene(scene);
stage.show();
}
public void addPieChartData(String name, double value) {
pieChartData.add(new Data(name, value));
caption = new Label();
caption.setTextFill(Color.DARKORANGE);
caption.setStyle("-fx-font: 24 arial;");
for (final Data data : chart.getData()) {
Node node = data.getNode();
node.addEventHandler(MouseEvent.MOUSE_MOVED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent e) {
caption.setTranslateX(e.getSceneX() + 15);
caption.setTranslateY(e.getSceneY());
caption.setText(String.valueOf(data.getPieValue()) + "%");
caption.setVisible(true);
node.setEffect(new Glow());
// String styleString = "-fx-border-color: white;
// -fx-border-width: 1; -fx-border-style: dashed;";
// node.setStyle(styleString);
}
});
node.addEventHandler(MouseEvent.MOUSE_EXITED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent e) {
caption.setVisible(false);
node.setEffect(null);
// node.setStyle("");
}
});
final MenuItem resizeItem = new MenuItem("Resize");
resizeItem.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
System.out.println("Resize requested");
}
});
final MenuItem aboutItem = new MenuItem("About");
aboutItem.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
System.out.println("About requested");
}
});
final MenuItem changeColorItem = new MenuItem("Change Color");
changeColorItem.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
System.out.println("change Color Item requested");
}
});
final ContextMenu menu = new ContextMenu(resizeItem, aboutItem, changeColorItem);
node.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
if (MouseButton.SECONDARY.equals(event.getButton())) {
menu.show(stage, event.getScreenX(), event.getScreenY());
}
}
});
}
}
// updates existing Data-Object if name matches
public void updatePieChart(List<FSPartitions> obj) {
Platform.runLater(new Runnable() {
@Override
public void run() {
for (FSPartitions obj1 : obj) {
String fsName = obj1.getFSName();
double usedSize = obj1.getUsedSize();
boolean found = false;
for (Data d : pieChartData) {
if (d.getName().equals(fsName)) {
d.setPieValue(usedSize);
found = true;
break;
}
}
if (!found) {
addPieChartData(fsName, usedSize);
}
}
}
});
}
public static void main(String[] args) {
launch(args);
}
}
这篇关于更新饼图中的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!