当前位置: 首页 > 知识库问答 >
问题:

如何用JavaFX解决Scene Builder中绘制图表的问题

端木涵润
2023-03-14

我的程序有问题。我想在提供数据后绘制图表(方程的系数)。

<?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">
            <font>
                <Font size="18.0" />
            </font>
        </Label>
        <LineChart fx:id="drawChart" prefHeight="598.0" prefWidth="800.0" title="Chart">
            <xAxis>
                <CategoryAxis side="BOTTOM" />
            </xAxis>
            <yAxis>
                <NumberAxis side="LEFT" />
            </yAxis>
        </LineChart>
        <Button fx:id="button" layoutX="317.0" layoutY="612.0" mnemonicParsing="false" prefHeight="61.0" prefWidth="98.0" text="Rysuj wykres" />
    </children>
</AnchorPane>
package grahps;

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 {

    private Controller controller;//

    @Override
    public void start(Stage stage) throws Exception {
        stage.show();


        System.out.println(getClass().getResource("/fxml/sample.fxml").getPath());
        FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/sample.fxml"));
        loader.setController(controller);
        Parent root = FXMLLoader.load(getClass().getResource("/fxml/sample.fxml"));
        Scene scene = new Scene(root, 800, 800);
        controller.drawChart(stage);
        stage.setScene(scene);
    }

    public static void main(String[] args) {
        launch(args);
    }
}
package grahps;
import javafx.fxml.FXML;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.control.TextField;
import javafx.scene.control.Label;
import javafx.scene.control.Button;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;

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
    XYChart.Series<Number, Number> chart;

    //Parser Text Field -> double
    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());

    @FXML
    public void drawChart(Stage stage) {
        XYChart.Series<Number, Number> series = chart;
        series.setName("Chart");

        final NumberAxis xAxis = new NumberAxis(xMin1, xMax1, 1);
        final NumberAxis yAxis = new NumberAxis();
        yAxis.setTickUnit(1);
        xAxis.setLabel("X Label");
        yAxis.setLabel("Y Label");
        final javafx.scene.chart.LineChart<Number, Number> lineChart = new javafx.scene.chart.LineChart<Number, Number>(xAxis, yAxis);
        double y;

        String pattern;
        if (a == 0 && c == 0) {
            pattern = "f(x)=" + factorB;
            label.setText(pattern);
        } else if (c == 0) {
            pattern = "f(x)=" + factorA + "x+" + factorB;
            label.setText(pattern);
            for (double i = xMin1; i <= xMax1; i++) {
                y = a * i + b;
                series.getData().add(new XYChart.Data(i, y));
            }
        } else {
            pattern = "f(x)=" + factorC + "x^2" + factorA + "x+" + factorB;
            label.setText(pattern);
            for (double i = xMin1; i < xMax1; i++) {
                y = a * i * i + b * i + c;
                series.getData().add(new XYChart.Data(i, y));
            }
        }

        lineChart.getData().add(series);
        Scene scene = new Scene(lineChart, 800, 800);
        stage.setScene(scene);
        stage.setResizable(false);
        stage.show();
    }
}

我会得到greaftul的帮助。

当我删除上面的@fxml注释并编译代码时,我得到了以下错误:

Exception in Application start method
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
    at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.RuntimeException: Exception in Application start method
    at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$154(LauncherImpl.java:182)
    at java.lang.Thread.run(Thread.java:748)
Caused by: javafx.fxml.LoadException: 
/C:/Users/Damian/IdeaProjects/Graphs/target/classes/fxml/sample.fxml:14

    at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2601)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2579)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3214)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3175)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3148)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3124)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3104)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3097)
    at grahps.Main.start(Main.java:22)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$161(LauncherImpl.java:863)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$174(PlatformImpl.java:326)
    at com.sun.javafx.application.PlatformImpl.lambda$null$172(PlatformImpl.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$173(PlatformImpl.java:294)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177)
    ... 1 more
Caused by: java.lang.NullPointerException
    at grahps.Controller.<init>(Controller.java:31)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at java.lang.Class.newInstance(Class.java:442)
    at sun.reflect.misc.ReflectUtil.newInstance(ReflectUtil.java:51)
    at javafx.fxml.FXMLLoader$ValueElement.processAttribute(FXMLLoader.java:927)
    at javafx.fxml.FXMLLoader$InstanceDeclarationElement.processAttribute(FXMLLoader.java:971)
    at javafx.fxml.FXMLLoader$Element.processStartElement(FXMLLoader.java:220)
    at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:744)
    at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2707)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2527)
    ... 17 more
Exception running application grahps.Main

Process finished with exit code 1

另外,我将onaction=“drawchart”更改为onaction=“chart”,现在我可以看到高亮显示的通信:“不能将javafx.scene.control.LineChart设置为chart”

共有1个答案

干茂才
2023-03-14

代码中有几个bug,例如:

>

  • 控制器中的//parser文本字段->double-block执行得太早=>NullPointerException

    当在开始-method中调用controller.drawchart(stage)时,controller=>NullPointerException

    在控制器系列中的drawchart-method等于null,因为chart等于null=>nullpointerexception

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

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

    >

  • 实现initialize-方法,在该方法中可以进行必要的初始化。

    实现updateChart-method,单击按钮时调用该方法并更新图表。

    定义对LineChart的引用。

    定义对两个轴的引用。

    因此,控制器-class如下所示:

    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*/}
    } 
    
    @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();
    }
    
      null
    <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);
    }
    

    getseries-method实质上包含drawchart-method的逻辑

    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-method中的最后三行。

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

    @FXML
    public void updateChart() {     
        XYChart.Series<Number, Number> series = getSeries();
        chart.getData().clear();
        chart.getData().add(series);
    }
    

    有些地方仍然可以改进,例如,如果改变窗口大小,应用程序就不能正确地缩放。此外,缺少对输入字段的验证。可以在initchartproperties-方法中禁用图表动画。

    更新:如果不显示符号,请在initchartproperties-method中添加:

    chart.setCreateSymbols(false);
    

    结果是:

  •  类似资料:
    • 我只想从JavaFX图表API生成一个图表图像。我不想显示应用程序窗口,也不想启动应用程序(如果没有必要)。 在start方法内部,我实际上需要访问外部数据以构建系列数据,但是似乎没有办法从start方法访问外部数据,如果我将数据存储在成员变量内部,则当开始叫做。我其实不在乎舞台和场景对象,只要图表图像可以渲染,我应该如何解决问题?我想建立一个可以用输入数据调用的API,用数据绘制图表,并返回文件

    • 我正在学习使用SceneBuilder创建一个新的JavaFX应用程序的教程,并尝试向.fxml文件添加一个controller类。 我正在使用Eclipse和Gluon的Scene Builder V8.1.1版本。 在哪里可以将我的.fxml文件连接到我的控制器Java类?

    • 本文向大家介绍解决seaborn在pycharm中绘图不出图的问题,包括了解决seaborn在pycharm中绘图不出图的问题的使用技巧和注意事项,需要的朋友参考一下 如下所示: 在代码最后加上plt.show( )即可。 以上这篇解决seaborn在pycharm中绘图不出图的问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持呐喊教程。

    • 任何人都可以帮助我解决这个问题AndroidManifest.xml mainactivity.kt

    • 本文向大家介绍python 解决cv2绘制中文乱码问题,包括了python 解决cv2绘制中文乱码问题的使用技巧和注意事项,需要的朋友参考一下 因为使用cv2.putText() 只能显示英文字符,中文会出现乱码问题, 因此使用PIL在图片上绘制添加中文,可以指定字体文件。 大体思路: OpenCV图片格式转换成PIL的图片格式; 使用PIL绘制文字; PIL图片格式转换成OpenCV的图片格式;

    • JavaFX中存在控件ToggleGroup。我已经安装了,版本: 在中找不到此控件: 谢谢你的帮助!