且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

JavaFX:如何在区域图表上动态添加几个系列并从图表中删除行(系列)?

更新时间:2023-01-24 22:50:25

这应该可以帮助您入门。我添加了一个 ArrayList 来跟上系列,它们被添加到 Chart 。评论在代码中。您可以弄清楚如何从 ArrayList 和/或图表中删除​​/删除项目,或者如何从 ArrayList 然后更新图表

  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
* /
公共类FXMLDocumentController实现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(); //使用ArrayList来保存新系列!


//按钮添加功能
@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));
}


//将系列添加到系列容器中。
seriesContainer.add(系列);

//只为AreaChart
添加新系列(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);
}
}


I am working with Area Chart of JavaFX. I want to add series dynamically after user will enter values in text fields and press Add button. I also want to add delete and undo functionality in it. Delete functionality working would be like for instance if there are several lines on the Area Chart each line represents series, user can delete any line he want by clicking on that line and after clicking on delete button. I also want to add undo functionality so user can undo his actions.

The interface is like this:

For example user can draw line like this by filling text fields:

Now let say the user want to delete the series which is in red color what I want is user click on it and after click delete button it'll delete the red series like this:

So far I've tried this:

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 file:

<?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>

Please someone guide me how can I achieve these functionalities.

This should help you get started. I added an ArrayList to keep up with Series that are added to the Chart. Comments are in the code. You can figure out how to delete/remove items from the ArrayList and/or Chart or how to remove items from the ArrayList then update the 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");
    }
}