我正在使用饼图来处理这个例子。我想动态创建数据并在每次生成新的自定义对象时更新饼图:
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;
}
}
我还想为饼图切片添加一些额外的标签。看起来我需要完全重新设计代码,因为每次我将拥有不同的数据,我需要可视化数据。我怎么能这个?你能帮我实现这个吗?
答案 0 :(得分:1)
您可以覆盖PieChart#layoutChartChildren
以在饼图切片的标签中显示其他值。我修改了你的代码来展示一个例子。为了添加值,我使用了您的更新线程,但使用变量&#34; l&#34;修改了usedSize
值。在动画中产生不断变化的值和标签。
以下示例中缺少FSPartitions类。
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);
}
}