为了账号安全,请及时绑定邮箱和手机立即绑定

如何解决使用 JavaFX 在场景生成器中绘制图表的问题

如何解决使用 JavaFX 在场景生成器中绘制图表的问题

qq_花开花谢_0 2023-07-28 10:38:54
我的程序有问题。我想在提供数据(方程的系数)后绘制图表。我尝试更改我的导入(它对某些变量有帮助)我更改了 java.awt* 为 javafx.scene ...(很少导入)。FXML 文件:<?xml version="1.0" encoding="UTF-8"?><?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.AnchorPane?><?import javafx.scene.text.Font?><AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="700.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8.0.172-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="grahps.Controller"><children>        <TextField fx:id="factorA" layoutX="24.0" layoutY="598.0" prefHeight="33.0" prefWidth="106.0" text="a=" AnchorPane.bottomAnchor="75.0" AnchorPane.leftAnchor="24.0" AnchorPane.rightAnchor="670.0" />        <TextField fx:id="factorB" layoutX="24.0" layoutY="630.0" prefHeight="33.0" prefWidth="106.0" text="b=" AnchorPane.bottomAnchor="37.0" AnchorPane.leftAnchor="24.0" AnchorPane.rightAnchor="670.0" />        <TextField fx:id="factorC" layoutX="24.0" layoutY="674.0" prefHeight="33.0" prefWidth="106.0" text="c=" AnchorPane.bottomAnchor="1.0" AnchorPane.leftAnchor="24.0" AnchorPane.rightAnchor="670.0" />        <TextField layoutX="158.0" layoutY="592.0" prefHeight="47.0" prefWidth="120.0" text="xMin=" AnchorPane.bottomAnchor="61.0" AnchorPane.leftAnchor="158.0" AnchorPane.rightAnchor="522.0" fx:id="xMin" />        <TextField layoutX="158.0" layoutY="650.0" prefHeight="47.0" prefWidth="120.0" text="xMax=" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="158.0" AnchorPane.rightAnchor="522.0" fx:id="xMax" />        <Label fx:id="label" layoutX="468.0" layoutY="629.0" prefHeight="61.0" prefWidth="276.0" text="f(x)=" AnchorPane.bottomAnchor="30.0" AnchorPane.leftAnchor="468.0" AnchorPane.rightAnchor="56.0">LineChart (fx:id="drawChart") 生成的部分进行通信:“未解析的 fx:id 参考
查看完整描述

1 回答

?
开满天机

TA贡献1786条经验 获得超12个赞

代码中有几个错误,例如:

  • //Parser Text Field -> double控制器中的 -block 执行得太早 = > NullPointerException

  • 当调用controller.drawChart(stage)-start方法controllerequals null=>时NullPointerException

  • drawChart控制器的 - 方法中seriesequals null,因为chartequals null=> NullPointerException

  • 控制器中缺少对图表的引用。这已经在评论中指出了。

  • CategoryAxis用作 x 轴的类型,尽管 x 数据是数值。

在修复这些错误之前,应该改进架构(这会自动修复一些错误):

  • Controller-class:由于图表必须初始化,然后在每次单击按钮时更新,因此控制器中的以下更改将很有用:

    因此,该Controller-class 如下所示:

    1. 实现一个initialize方法,可以在其中进行必要的初始化。

    2. 实现一个updateChart- 方法,该方法在单击按钮时调用并更新图表。

    3. 定义对折线图的引用。

    4. 定义对两个轴的参考。

public class Controller {

    @FXML

    TextField factorA;

    @FXML

    TextField factorB;

    @FXML

    TextField factorC;

    @FXML

    TextField xMin;

    @FXML

    TextField xMax;

    @FXML

    Label label;

    @FXML

    Button button;

    @FXML

    LineChart<Number, Number> chart; 

    @FXML

    NumberAxis xAxis;

    @FXML

    NumberAxis yAxis;

    @FXML

    public void updateChart() {/*ToDo*/}

    public void initialize(){/*ToDo*/}

Main-class:在start-method 中,仅需要加载 FXML:


@Override

public void start(Stage stage) throws Exception {

    Parent root = FXMLLoader.load(getClass().getResource("/fxml/sample.fxml"));

    Scene scene = new Scene(root, 800, 800);

    stage.setScene(scene);

    stage.show();

}

FXML:应进行以下更改:

  1. 将折线图的 ID 更改为fx:id="chart"

  2. 将 LineChart 的 x 轴类型更改为NumberAxis

  3. 添加onAction="#updateChart"到按钮。updateChart单击按钮时将调用- 方法。

  4. fx:id="xAxis"为两个轴(和)定义 ID fx:id="yAxis"

  5. 删除所有文本字段的所有非数字字符(例如text="a=")的初始化,否则解析会出现问题(使用标签或水印更有意义,例如promptText="a")。

然后,FXML 变为:

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="700.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8.0.172-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="grahps.Controller">

    <children>

        <TextField fx:id="factorA" prefHeight="33.0" prefWidth="106.0" AnchorPane.bottomAnchor="75.0" AnchorPane.leftAnchor="24.0" AnchorPane.rightAnchor="670.0" promptText="a" />

        <TextField fx:id="factorB" prefHeight="33.0" prefWidth="106.0" AnchorPane.bottomAnchor="37.0" AnchorPane.leftAnchor="24.0" AnchorPane.rightAnchor="670.0" promptText="b" />

        <TextField fx:id="factorC" prefHeight="33.0" prefWidth="106.0" AnchorPane.bottomAnchor="1.0" AnchorPane.leftAnchor="24.0" AnchorPane.rightAnchor="670.0" promptText="c" />

        <TextField fx:id="xMin" prefHeight="47.0" prefWidth="120.0" AnchorPane.bottomAnchor="61.0" AnchorPane.leftAnchor="158.0" AnchorPane.rightAnchor="522.0" promptText="xMin" />

        <TextField fx:id="xMax" prefHeight="47.0" prefWidth="120.0" AnchorPane.bottomAnchor="3.0" AnchorPane.leftAnchor="158.0" AnchorPane.rightAnchor="522.0" promptText="xMax" />

        <Label fx:id="label" prefHeight="61.0" prefWidth="276.0" AnchorPane.bottomAnchor="30.0" AnchorPane.leftAnchor="468.0" AnchorPane.rightAnchor="56.0" text="f(x)=" >

            <font>

                <Font size="18.0" />

            </font>

        </Label>

        <LineChart fx:id="chart" prefHeight="598.0" prefWidth="800.0" title="Chart">

            <xAxis>

                <NumberAxis fx:id="xAxis" side="BOTTOM" />

            </xAxis>

            <yAxis>

                <NumberAxis fx:id="yAxis" side="LEFT" />

            </yAxis>

        </LineChart>

        <Button fx:id="button" prefHeight="61.0" prefWidth="98.0" layoutX="317.0" layoutY="612.0" mnemonicParsing="false" text="Rysuj wykres" onAction="#updateChart" />

    </children>

</AnchorPane>

通过这些更改,应用程序启动时会显示一个空图表(因为尚未实现初始化)。单击该按钮没有任何效果(因为尚未实施更新)。


初始化:


public void initialize(){       

    initChartProperties();

    initInputControls();        

    XYChart.Series<Number, Number> series = getSeries();        

    chart.getData().add(series);

}

-methodgetSeries本质上包含 -method 的逻辑drawChart:


private XYChart.Series<Number, Number> getSeries() {


    double xMax1 = Double.parseDouble(xMax.getText());

    double xMin1 = Double.parseDouble(xMin.getText());

    double a = Double.parseDouble(factorA.getText());

    double b = Double.parseDouble(factorB.getText());

    double c = Double.parseDouble(factorC.getText());


    XYChart.Series<Number,Number> series = new XYChart.Series<Number, Number>();

    series.setName("Chart");


    String pattern;

    if (a == 0 && c == 0) {

        pattern = "f(x)=" + factorB.getText();

        label.setText(pattern);

    } else if (c == 0) {

        pattern = "f(x)=" + factorA.getText() + "x+" + factorB.getText();

        label.setText(pattern);

        for (double i = xMin1; i <= xMax1; i++) {

            double y = a * i + b;

            series.getData().add(new Data<Number, Number>(i, y));

        }

    } else {

        pattern = "f(x)=" + factorA.getText() + "x^2+" + factorB.getText() + "x+" + factorC.getText();

        label.setText(pattern);

        for (double i = xMin1; i < xMax1; i++) {

            double y = a * i * i + b * i + c;

            series.getData().add(new Data<Number, Number>(i, y));

        }

    }


    return series;

}

-方法initInputControls初始化输入控件,例如:


private void initInputControls() {

    xMax.setText("100.0");

    xMin.setText("10.0");

    factorA.setText("1.0");

    factorB.setText("2.0");

    factorC.setText("3.0");

}

-方法initChartProperties初始化图表:


private void initChartProperties() {

    chart.setAnimated(true);

    xAxis.setLabel("X Label");

    yAxis.setLabel("Y Label");      

}

如果您想在启动时显示空图表,只需删除 - 方法中的最后三行即可initialize。


更新:更新只是删除旧系列并将新系列添加到图表中:


@FXML

public void updateChart() {     

    XYChart.Series<Number, Number> series = getSeries();

    chart.getData().clear();

    chart.getData().add(series);

}

进行这些更改后,应用程序将按预期运行。左图显示启动后的应用程序,右图显示更新输入值后的应用程序。

//img1.sycdn.imooc.com//64c32a830001a2ab12550647.jpg

有些事情仍然可以改进,例如,如果窗口大小更改,应用程序将无法正确缩放。此外,缺少输入字段的验证。可以在 - 方法中禁用图表动画initChartProperties

更新: 如果不显示任何符号,请添加 -initChartProperties方法:

chart.setCreateSymbols(false);

结果是:

//img1.sycdn.imooc.com//64c32a9600018cba12630645.jpg

查看完整回答
反对 回复 2023-07-28
  • 1 回答
  • 0 关注
  • 112 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信