JavaFX:如何在面积图上动态添加多个系列并从图表中删除线(系列)?
JavaFX: How to add serveral series dynimically on Area Chart and delete line(series) from chart?
我正在使用 JavaFX 的面积图。我想在用户在文本字段中输入值并按下添加按钮后动态添加系列。我还想在其中添加删除和撤消功能。例如,如果面积图上有几条线,每条线代表系列,用户可以通过单击该线并在单击删除按钮后删除他想要的任何线。我还想添加撤消功能,以便用户可以撤消他的操作。
界面是这样的:
例如,用户可以通过填充文本字段来画线:
现在假设用户想要删除红色系列,我想要的是用户点击它,点击删除按钮后,它将像这样删除红色系列:
到目前为止我试过这个:
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.chart.AreaChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.control.TextField;
import javafx.scene.input.MouseEvent;
public class SampleController {
@FXML
private NumberAxis xAxis;
@FXML
private NumberAxis yAxis;
@FXML
private AreaChart<Number, Number> areaChart;
@FXML
private TextField txtSt;
@FXML
private TextField txtEt;
@FXML
private TextField txtNb;
public void initialize() {
areaChart.setTitle("Chronos");
xAxis.setLabel("Heures");
yAxis.setLabel("Employés");
}
//Button add functionality
@FXML
private void generateGraph() {
//double start = Double.parseDouble(txtSt.getText());
double end = Double.parseDouble(txtEt.getText());
int numberEmployees = Integer.parseInt(txtNb.getText());
XYChart.Series<Number, Number> series= new XYChart.Series<>();
for (double start = Double.parseDouble(txtSt.getText()); start<=end; start++) {
series.getData().add(new XYChart.Data<Number, Number>(start, numberEmployees));
}
// Add Series to AreaChart.
areaChart.getData().add(series);
//Mouse click even for series
setOnMouseEventsOnSeries(series.getNode(),
areaChart, "Series is clicked");
}
private void setOnMouseEventsOnSeries(Node node,
final AreaChart chart, final String label) {
node.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent t) {
chart.setTitle(label);
}
});
}
}
FXML 文件:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.chart.AreaChart?>
<?import javafx.scene.chart.NumberAxis?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<VBox alignment="CENTER" prefHeight="800.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.SampleController">
<children>
<AreaChart fx:id="areaChart" prefHeight="799.0" prefWidth="800.0" VBox.vgrow="ALWAYS">
<xAxis>
<NumberAxis autoRanging="false" minorTickCount="1" minorTickLength="1.0" side="BOTTOM" tickLabelGap="1.0" tickLength="1.0" tickUnit="1.0" upperBound="24.0" fx:id="xAxis" />
</xAxis>
<yAxis>
<NumberAxis fx:id="yAxis" autoRanging="false" minorTickLength="1.0" side="LEFT" tickLabelGap="1.0" tickUnit="1.0" upperBound="10.0" />
</yAxis>
</AreaChart>
<HBox alignment="CENTER" prefHeight="193.0" prefWidth="800.0">
<children>
<TextField fx:id="txtSt" promptText="Start Value" />
<TextField fx:id="txtEt" promptText="End Value" />
<TextField fx:id="txtNb" promptText="Number of Employees" />
</children>
</HBox>
<HBox alignment="CENTER" prefHeight="71.0" prefWidth="800.0">
<children>
<Button mnemonicParsing="false" onAction="#generateGraph" prefHeight="31.0" prefWidth="137.0" text="Add" />
<Button layoutX="342.0" layoutY="12.0" mnemonicParsing="false" prefHeight="31.0" prefWidth="137.0" text="Delete" />
<Button layoutX="410.0" layoutY="12.0" mnemonicParsing="false" prefHeight="31.0" prefWidth="137.0" text="Undo" />
</children>
</HBox>
</children>
</VBox>
请有人指导我如何实现这些功能。
这应该可以帮助您入门。我添加了一个 ArrayList
来跟上添加到 Chart
的 Series
。注释在代码中。您可以找出如何 ArrayList
and/or Chart
中的 delete/remove 项目或如何从 ArrayList
中删除项目然后更新 Chart
。
import java.net.URL;
import java.util.ArrayList;
import java.util.ResourceBundle;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.chart.AreaChart;
import javafx.scene.chart.XYChart;
import javafx.scene.control.TextField;
import javafx.scene.input.MouseEvent;
/**
*
* @author blj0011
*/
public class FXMLDocumentController implements Initializable {
// @FXML
// private NumberAxis xAxis;
// @FXML
// private NumberAxis yAxis;
@FXML
private AreaChart<Number, Number> areaChart;
@FXML
private TextField txtSt;
@FXML
private TextField txtEt;
@FXML
private TextField txtNb;
ArrayList<XYChart.Series<Number, Number>> seriesContainer = new ArrayList();//Use an ArrayList to hold new Series!
//Button add functionality
@FXML
private void generateGraph() {
Double start = Double.parseDouble(txtSt.getText());
Double end = Double.parseDouble(txtEt.getText());
double numberEmployees = Integer.parseInt(txtNb.getText());
XYChart.Series<Number, Number> series= new XYChart.Series<>();
for (int i = start.intValue(); i <= end.intValue(); i++) {
series.getData().add(new XYChart.Data(i, numberEmployees));
}
// Add Series to series container.
seriesContainer.add(series);
//Add only new series to AreaChart
for(XYChart.Series<Number, Number> entry : seriesContainer)
{
if(!areaChart.getData().contains(entry))
{
areaChart.getData().add(entry);
}
}
}
private void setOnMouseEventsOnSeries(Node node,
final AreaChart chart, final String label) {
node.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent t) {
chart.setTitle(label);
}
});
}
@Override
public void initialize(URL location, ResourceBundle resources) {
areaChart.setTitle("Chronos");
areaChart.getXAxis().setLabel("Heures");
areaChart.getYAxis().setLabel("Employés");
}
}
我正在使用 JavaFX 的面积图。我想在用户在文本字段中输入值并按下添加按钮后动态添加系列。我还想在其中添加删除和撤消功能。例如,如果面积图上有几条线,每条线代表系列,用户可以通过单击该线并在单击删除按钮后删除他想要的任何线。我还想添加撤消功能,以便用户可以撤消他的操作。
界面是这样的:
例如,用户可以通过填充文本字段来画线:
现在假设用户想要删除红色系列,我想要的是用户点击它,点击删除按钮后,它将像这样删除红色系列:
到目前为止我试过这个:
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.chart.AreaChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.control.TextField;
import javafx.scene.input.MouseEvent;
public class SampleController {
@FXML
private NumberAxis xAxis;
@FXML
private NumberAxis yAxis;
@FXML
private AreaChart<Number, Number> areaChart;
@FXML
private TextField txtSt;
@FXML
private TextField txtEt;
@FXML
private TextField txtNb;
public void initialize() {
areaChart.setTitle("Chronos");
xAxis.setLabel("Heures");
yAxis.setLabel("Employés");
}
//Button add functionality
@FXML
private void generateGraph() {
//double start = Double.parseDouble(txtSt.getText());
double end = Double.parseDouble(txtEt.getText());
int numberEmployees = Integer.parseInt(txtNb.getText());
XYChart.Series<Number, Number> series= new XYChart.Series<>();
for (double start = Double.parseDouble(txtSt.getText()); start<=end; start++) {
series.getData().add(new XYChart.Data<Number, Number>(start, numberEmployees));
}
// Add Series to AreaChart.
areaChart.getData().add(series);
//Mouse click even for series
setOnMouseEventsOnSeries(series.getNode(),
areaChart, "Series is clicked");
}
private void setOnMouseEventsOnSeries(Node node,
final AreaChart chart, final String label) {
node.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent t) {
chart.setTitle(label);
}
});
}
}
FXML 文件:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.chart.AreaChart?>
<?import javafx.scene.chart.NumberAxis?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<VBox alignment="CENTER" prefHeight="800.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.SampleController">
<children>
<AreaChart fx:id="areaChart" prefHeight="799.0" prefWidth="800.0" VBox.vgrow="ALWAYS">
<xAxis>
<NumberAxis autoRanging="false" minorTickCount="1" minorTickLength="1.0" side="BOTTOM" tickLabelGap="1.0" tickLength="1.0" tickUnit="1.0" upperBound="24.0" fx:id="xAxis" />
</xAxis>
<yAxis>
<NumberAxis fx:id="yAxis" autoRanging="false" minorTickLength="1.0" side="LEFT" tickLabelGap="1.0" tickUnit="1.0" upperBound="10.0" />
</yAxis>
</AreaChart>
<HBox alignment="CENTER" prefHeight="193.0" prefWidth="800.0">
<children>
<TextField fx:id="txtSt" promptText="Start Value" />
<TextField fx:id="txtEt" promptText="End Value" />
<TextField fx:id="txtNb" promptText="Number of Employees" />
</children>
</HBox>
<HBox alignment="CENTER" prefHeight="71.0" prefWidth="800.0">
<children>
<Button mnemonicParsing="false" onAction="#generateGraph" prefHeight="31.0" prefWidth="137.0" text="Add" />
<Button layoutX="342.0" layoutY="12.0" mnemonicParsing="false" prefHeight="31.0" prefWidth="137.0" text="Delete" />
<Button layoutX="410.0" layoutY="12.0" mnemonicParsing="false" prefHeight="31.0" prefWidth="137.0" text="Undo" />
</children>
</HBox>
</children>
</VBox>
请有人指导我如何实现这些功能。
这应该可以帮助您入门。我添加了一个 ArrayList
来跟上添加到 Chart
的 Series
。注释在代码中。您可以找出如何 ArrayList
and/or Chart
中的 delete/remove 项目或如何从 ArrayList
中删除项目然后更新 Chart
。
import java.net.URL;
import java.util.ArrayList;
import java.util.ResourceBundle;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Node;
import javafx.scene.chart.AreaChart;
import javafx.scene.chart.XYChart;
import javafx.scene.control.TextField;
import javafx.scene.input.MouseEvent;
/**
*
* @author blj0011
*/
public class FXMLDocumentController implements Initializable {
// @FXML
// private NumberAxis xAxis;
// @FXML
// private NumberAxis yAxis;
@FXML
private AreaChart<Number, Number> areaChart;
@FXML
private TextField txtSt;
@FXML
private TextField txtEt;
@FXML
private TextField txtNb;
ArrayList<XYChart.Series<Number, Number>> seriesContainer = new ArrayList();//Use an ArrayList to hold new Series!
//Button add functionality
@FXML
private void generateGraph() {
Double start = Double.parseDouble(txtSt.getText());
Double end = Double.parseDouble(txtEt.getText());
double numberEmployees = Integer.parseInt(txtNb.getText());
XYChart.Series<Number, Number> series= new XYChart.Series<>();
for (int i = start.intValue(); i <= end.intValue(); i++) {
series.getData().add(new XYChart.Data(i, numberEmployees));
}
// Add Series to series container.
seriesContainer.add(series);
//Add only new series to AreaChart
for(XYChart.Series<Number, Number> entry : seriesContainer)
{
if(!areaChart.getData().contains(entry))
{
areaChart.getData().add(entry);
}
}
}
private void setOnMouseEventsOnSeries(Node node,
final AreaChart chart, final String label) {
node.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent t) {
chart.setTitle(label);
}
});
}
@Override
public void initialize(URL location, ResourceBundle resources) {
areaChart.setTitle("Chronos");
areaChart.getXAxis().setLabel("Heures");
areaChart.getYAxis().setLabel("Employés");
}
}