Построение в javafx приводит к тому, что ClassCastException Double не может преобразовать в String

Я выполнял университетский проект по построению решения дифференциального уравнения под названием модель Лотки-Вольтерри. Речь идет об отношениях между жертвами и хищниками в природе. Окно отображается нормально, когда я нажимаю любую из кнопок, программа выдает исключение в консоли. Я пытался самостоятельно разобраться, что не так, около 2 часов безрезультатно.

Класс для создания данных работает по назначению, я создал csv-generator и построил его в excel.

Вот мой класс контроллера:

package sample;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.chart.LineChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import org.apache.commons.math3.ode.FirstOrderDifferentialEquations;
import org.apache.commons.math3.ode.FirstOrderIntegrator;
import org.apache.commons.math3.ode.nonstiff.EulerIntegrator;

import java.util.ArrayList;

public class Controller {

    private double aHolder = -1;
    private double bHolder = -1;
    private double cHolder = -1;
    private double dHolder = -1;

    //datasets
    private XYChart.Series XT = new XYChart.Series();
    private XYChart.Series VT = new XYChart.Series();
    private XYChart.Series VX = new XYChart.Series();

    @FXML
    private TextField textA;

    @FXML
    private TextField textB;

    @FXML
    private TextField textC;

    @FXML
    private TextField textD;

    @FXML
    private Button plotXT;

    @FXML
    private Button plotVT;

    @FXML
    private Button plotVX;

    @FXML
    private LineChart<Number, Number> figure;

    @FXML
    private NumberAxis t;

    @FXML
    private NumberAxis x;

    @FXML
    void onclickPlotVT(ActionEvent event) {
        boolean isTheSame = checkIfTheSameAndSetIfNot();
        if (!isTheSame){
            calculate();
        }
        figure.getData().clear();
        figure.getData().add(VT);

    }

    @FXML
    void onclickPlotVX(ActionEvent event) {
        boolean isTheSame = checkIfTheSameAndSetIfNot();
        if (!isTheSame){
            calculate();
        }
        figure.getData().clear();
        figure.getData().add(VX);

    }

    @FXML
    void onclickPlotXT(ActionEvent event) {
        boolean isTheSame = checkIfTheSameAndSetIfNot();
        if (!isTheSame){
            calculate();
        }
        figure.getData().clear();
        figure.getData().add(XT);

    }

    //if
     private boolean checkIfTheSameAndSetIfNot(){
        double currentA = Double.parseDouble(textA.getText());
        double currentB = Double.parseDouble(textB.getText());
        double currentC = Double.parseDouble(textC.getText());
        double currentD = Double.parseDouble(textD.getText());

        boolean checkA = currentA == aHolder;
        boolean checkB = currentB == bHolder;
        boolean checkC = currentC == cHolder;
        boolean checkD = currentD == dHolder;

        //if all parameters are the same, return true, other way false
        if (checkA && checkB && checkC && checkD){
            return true;
        }

        aHolder = currentA;
        bHolder = currentB;
        cHolder = currentC;
        dHolder = currentD;

        return false;
    }

    private void calculate(){
        FirstOrderDifferentialEquations diffEquSolver = new DiffEquSolverZad2(aHolder, bHolder, cHolder, dHolder);
        FirstOrderIntegrator diffEquLIntegrator = new EulerIntegrator(0.01);
        DiffEquSolverPath diffSolverEquPath = new DiffEquSolverPath();
        double [] xStart = new double [] {0,0};
        double [] xStop = new double [] {10,10};
        diffEquLIntegrator.addStepHandler(diffSolverEquPath);
        diffEquLIntegrator.integrate(diffEquSolver,0,xStart,20,xStop);

        ArrayList<String> csv = diffSolverEquPath.getCsv();

        for(String s : csv){
            String data[] = s.split(",");
            XT.getData().add(new XYChart.Data(Double.parseDouble(data[0]), Double.parseDouble(data[1])));
            VT.getData().add(new XYChart.Data(Double.parseDouble(data[0]), Double.parseDouble(data[2])));
            VX.getData().add(new XYChart.Data(Double.parseDouble(data[1]), Double.parseDouble(data[2])));

        }

        System.out.println();
    }

}

Основной класс содержит только создание и промывку сцены, сгенерированной SceneBuilder.

Положение стека после выброса исключения выглядит так:

Exception in thread "JavaFX Application Thread" java.lang.ClassCastException: class java.lang.Double cannot be cast to class java.lang.String (java.lang.Double and java.lang.String are in module java.base of loader 'bootstrap')
    at javafx.controls/javafx.scene.chart.CategoryAxis.invalidateRange(CategoryAxis.java:456)
    at javafx.controls/javafx.scene.chart.LineChart.updateAxisRange(LineChart.java:207)
    at javafx.controls/javafx.scene.chart.XYChart.layoutChartChildren(XYChart.java:670)
    at javafx.controls/javafx.scene.chart.Chart$1.layoutChildren(Chart.java:95)
    at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1204)
    at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1211)
    at javafx.graphics/javafx.scene.Parent.layout(Parent.java:1211)
    at javafx.graphics/javafx.scene.Scene.doLayoutPass(Scene.java:576)
    at javafx.graphics/javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2482)
    at javafx.graphics/com.sun.javafx.tk.Toolkit.lambda$runPulse$2(Toolkit.java:412)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at javafx.graphics/com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:411)
    at javafx.graphics/com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:438)
    at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:519)
    at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:499)
    at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.pulseFromQueue(QuantumToolkit.java:492)
    at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$11(QuantumToolkit.java:320)
    at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
    at java.base/java.lang.Thread.run(Thread.java:834)

Другие классы (работающие по назначению):

package sample;

import org.apache.commons.math3.exception.DimensionMismatchException;
import org.apache.commons.math3.exception.MaxCountExceededException;
import org.apache.commons.math3.ode.FirstOrderDifferentialEquations;

public class DiffEquSolverZad2 implements FirstOrderDifferentialEquations {
    private double a;
    private double b;
    private double c;
    private double d;


    public DiffEquSolverZad2(double a, double b, double c, double d) {
        if (a > 0 && b > 0 && c > 0 && d > 0) {
            this.a = a;
            this.b = b;
            this.c = c;
            this.d = d;
        } else {
            throw new IllegalArgumentException("All parameters must be greater than 0. ");
        }
    }



    @Override
    public int getDimension() {
        return 2;
    }

    @Override
    public void computeDerivatives(double t, double[] x, double[] dxdt) throws MaxCountExceededException, DimensionMismatchException {
        dxdt[0]= (a-b*x[1])*x[0];
        dxdt[1]= (c*x[0]-d)*x[1];
    }
}


package sample;

import org.apache.commons.math3.exception.MaxCountExceededException;
import org.apache.commons.math3.ode.sampling.StepHandler;
import org.apache.commons.math3.ode.sampling.StepInterpolator;

import java.util.ArrayList;
import java.util.Arrays;

public class DiffEquSolverPath implements StepHandler {

    private ArrayList<String> csv = new ArrayList<>();
    private ArrayList<Double> tValues = new ArrayList<>();

    public ArrayList<String> getCsv() {
        return csv;
    }

    public void clearCSVArray(){
        csv.clear();
    }

    @Override
    public void init(double v, double[] doubles, double v1) {

    }

    @Override
    public void handleStep(StepInterpolator stepInterpolator, boolean b) throws MaxCountExceededException {
        double t=stepInterpolator.getCurrentTime();//czas dla którego otrzymaliśmy rozwiązanie numeryczne(obliczono wartości xi v)
        double [] x=stepInterpolator.getInterpolatedState(); //wartości x i v

        csv.add(t+", "+ Arrays.toString(x).replace("[", "").replace("]", ""));

        tValues.add(t);
    }
}

    package sample;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        primaryStage.setTitle("Zad5 from L5 Numeric Methods. ");
        primaryStage.setScene(new Scene(root, 1000, 600));
        primaryStage.show();
    }


    public static void main(String[] args) {
        launch(args);
    }
}

Файл FXML:

<?xml version = "1.0" encoding = "UTF-8"?>

<?import javafx.geometry.Insets?>
<?import javafx.scene.chart.CategoryAxis?>
<?import javafx.scene.chart.LineChart?>
<?import javafx.scene.chart.NumberAxis?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>

<BorderPane maxHeight = "-Infinity" maxWidth = "-Infinity" minHeight = "-Infinity" minWidth = "-Infinity" prefHeight = "389.0" prefWidth = "933.0" xmlns = "http://javafx.com/javafx/10.0.1" xmlns:fx = "http://javafx.com/fxml/1" fx:controller = "sample.Controller">
   <opaqueInsets>
      <Insets bottom = "20.0" left = "20.0" right = "20.0" top = "20.0" />
   </opaqueInsets>
   <top>
      <VBox prefHeight = "78.0" prefWidth = "563.0" BorderPane.alignment = "CENTER">
         <children>
            <HBox alignment = "CENTER" prefHeight = "100.0" prefWidth = "200.0" spacing = "20.0">
               <children>
                  <Label prefHeight = "50.0" prefWidth = "119.0" text = "Model Lotki-Volterry">
                     <font>
                        <Font name = "System Bold" size = "12.0" />
                     </font>
                  </Label>
                  <Label text = "a:" />
                  <TextField fx:id = "textA" promptText = "1" />
                  <Label text = "b:" />
                  <TextField fx:id = "textB" promptText = "1" />
                  <Label text = "c:" />
                  <TextField fx:id = "textC" promptText = "1" />
                  <Label text = "d:" />
                  <TextField fx:id = "textD" promptText = "1" />
               </children>
            </HBox>
            <HBox alignment = "CENTER" prefHeight = "100.0" prefWidth = "200.0" spacing = "30.0">
               <children>
                  <VBox alignment = "CENTER" prefHeight = "39.0" prefWidth = "286.0">
                     <children>
                        <Label text = "a – współczynnik przyrostu ofiar" />
                        <Label text = "b – częstość umierania ofiar na skutek drapieżnictwa" />
                     </children>
                  </VBox>
                  <VBox alignment = "CENTER" prefHeight = "39.0" prefWidth = "266.0">
                     <children>
                        <Label text = "c – współczynnik przyrostu drapieżników" />
                        <Label text = "d – częstość umierania drapieżników" />
                     </children>
                  </VBox>
                  <Button fx:id = "plotXT" mnemonicParsing = "false" onAction = "#onclickPlotXT" text = "Wykres x(t)" />
                  <Button fx:id = "plotVT" mnemonicParsing = "false" onAction = "#onclickPlotVT" text = "Wykres v(t)" />
                  <Button fx:id = "plotVX" mnemonicParsing = "false" onAction = "#onclickPlotVX" text = "Wykres v(x)" />
               </children>
            </HBox>
         </children>
      </VBox>
   </top>
   <center>
      <LineChart fx:id = "figure" prefHeight = "249.0" prefWidth = "563.0" BorderPane.alignment = "CENTER">
        <xAxis>
          <CategoryAxis side = "BOTTOM" />
        </xAxis>
        <yAxis>
          <NumberAxis side = "LEFT" />
        </yAxis>
      </LineChart>
   </center>
</BorderPane>

Дубликат этого вопрос. Тем не менее, проблема может быть отправлена ​​для Scene Builder здесь, чтобы разрешить изменение типа оси.

José Pereda 21.11.2018 11:02

Но тип оси - числа. private LineChart<Number, Number> figure;, на классах так и сделали, попробую поставить Double вставкой из Number.

Embid123 21.11.2018 11:06

Не в вашем FXML. Прочтите связанный мной вопрос и его решение.

José Pereda 21.11.2018 11:07

Я, должно быть, пропустил это ... Большое спасибо.

Embid123 21.11.2018 11:09
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
4
775
0

Другие вопросы по теме