有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Javafx将文本字段中当前的值保存到外部txt文件

我正在为学校创建一个省钱项目,目标是你想存多少钱,计算你一周挣多少钱,并根据你花多少钱和存多少钱来编辑你的目标。我目前正试图在一个文本字段中实现这个目标,以便在程序关闭时保存到一个txt文件中。然而,无论我如何尝试修复它,我都会得到一个NullPointerException或textfield的值另存为“null”

下面是main(我试图将目标变量保存在stop()方法中)

package sample;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.TextField;
import javafx.stage.Stage;
import java.io.*;


public class Main extends Application  {

@FXML
public TextField finalGoal;

@Override
public void start(Stage primaryStage)throws Exception  {
    File f = new File("Goal.txt");
    boolean bool = false;
    if (f.exists() )
    {
        Parent root = FXMLLoader.load(getClass().getResource("MainPage.fxml"));
        primaryStage.setTitle("Money Saver Program");
        primaryStage.setScene(new Scene(root, 600, 400));
        primaryStage.show();


    }
    else
    {
        bool = f.createNewFile();
        Parent root = FXMLLoader.load(getClass().getResource("OpeningPage.fxml"));
        primaryStage.setTitle("Money Saver Program");
        primaryStage.setScene(new Scene(root, 638, 400));
        primaryStage.show();

    }

    primaryStage.setOnCloseRequest(e -> closeProgram());

}

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

public void closeProgram(){

    Platform.exit();
}

@Override
public void stop()throws Exception{
    PrintWriter write = new PrintWriter("Goal.txt");
    String end;
    end = finalGoal.getAccessibleText();
    write.write(end);
    write.close();
}
}

这是文本字段所在的fxml的控制器

package sample;

  import javafx.application.Platform;
  import javafx.event.ActionEvent;
  import javafx.fxml.FXML;
  import javafx.fxml.FXMLLoader;
  import javafx.scene.Node;
  import javafx.scene.Parent;
  import javafx.scene.Scene;
  import javafx.scene.control.TextField;
  import javafx.stage.Stage;
  import java.io.*;
  import java.io.FileReader;
  import javax.annotation.PostConstruct;

  public class MainPageController {

@FXML
public TextField finalGoal;

@FXML
private Stage myStage;

//Method that reads the current goal saved in an external textfile.
@PostConstruct
public void initialize() throws Exception{
    //Initialize Reader
    FileReader reader = new FileReader("Goal.txt");
    BufferedReader br = new BufferedReader(reader);

    //Store goal in the textField
    finalGoal.setText(br.readLine());

    //Close Reader
    reader.close();


}

//Method that handles close request and handles the current scene and controller
@PostConstruct
public void start(Stage stage1)throws Exception{
    myStage = stage1;
    FXMLLoader loader = new FXMLLoader(getClass().getResource("MainPage.fxml"));
    Parent root = loader.load();
    loader.getController();
    loader.load();
    loader.getController();
    stage1.getScene().getWindow();
    myStage.setOnCloseRequest(e -> onEnd());
}

public void openPage1(ActionEvent event) throws Exception {
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("MandatoryCostCollector.fxml"));
    Parent root = fxmlLoader.load();
    Stage stage = new Stage();
    stage.setScene(new Scene(root));
    stage.setTitle("Money Saver Program");
    stage.show();
    ((Node) event.getSource()).getScene().getWindow().hide();
}

public void openPage2(ActionEvent event) throws Exception {
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("PayDataCollector.fxml"));
    Parent root = fxmlLoader.load();
    Stage stage = new Stage();
    stage.setScene(new Scene(root));
    stage.setTitle("Money Saver Program");
    stage.show();
    ((Node) event.getSource()).getScene().getWindow().hide();
}

public void resetGoal(ActionEvent event) throws Exception {
    finalGoal.setText("");
}

public void onEnd(){
    Platform.exit();
}

}

这是fxml文件

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

<?import javafx.scene.text.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>

<BorderPane fx:id="BorderPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.MainPageController">
   <top>
  <VBox prefHeight="65.0" prefWidth="600.0" BorderPane.alignment="CENTER">
     <children>
        <TextField alignment="CENTER" editable="false" prefHeight="68.0" prefWidth="600.0" text="Welcome to the Money Saving Program">
           <font>
              <Font name="Arial Rounded MT Bold" size="26.0" />
           </font>
        </TextField>
     </children>
  </VBox>
   </top>
   <left>
  <VBox prefHeight="335.0" prefWidth="159.0" BorderPane.alignment="CENTER">
     <children>
        <Button fx:id="openPage1" mnemonicParsing="false" onAction="#openPage1" prefHeight="88.0" prefWidth="167.0" text="1. Open Mandatory Cost Collector" wrapText="true">
           <font>
              <Font name="Arial" size="18.0" />
           </font>
        </Button>
        <Button fx:id="openPage2" mnemonicParsing="false" onAction="#openPage2" prefHeight="60.0" prefWidth="173.0" text="2. Open Pay Data Collector" wrapText="true">
           <font>
              <Font name="Arial" size="18.0" />
           </font>
        </Button>
     </children>
  </VBox>
   </left>
   <right>
  <VBox prefHeight="335.0" prefWidth="166.0" BorderPane.alignment="CENTER">
     <children>
        <TextField fx:id="finalGoal" promptText="\$">
           <font>
              <Font name="Arial" size="40.0" />
           </font>
        </TextField>
        <Button fx:id="resetGoal" contentDisplay="RIGHT" mnemonicParsing="false" onAction="#resetGoal" prefHeight="33.0" prefWidth="173.0" text="Reset Goal" wrapText="true">
           <font>
              <Font name="Arial" size="18.0" />
           </font>
        </Button>
     </children>
  </VBox>
   </right>
   <bottom>
  <HBox prefHeight="100.0" prefWidth="200.0" BorderPane.alignment="CENTER">
     <children>
        <Button fx:id="generateNewGoal" mnemonicParsing="false" prefHeight="63.0" prefWidth="161.0" text="3. Generate your new goal" translateY="36.0" wrapText="true">
           <font>
              <Font name="Arial" size="18.0" />
           </font>
        </Button>
        <TextField alignment="CENTER" editable="false" prefHeight="75.0" prefWidth="221.0" text="Money saved this week" translateX="38.0" translateY="23.0">
           <font>
              <Font name="Arial" size="18.0" />
           </font>
        </TextField>
        <TextField fx:id="moneySaved" editable="false" prefHeight="75.0" prefWidth="180.0" promptText="\$" translateX="38.0" translateY="23.0">
           <font>
              <Font name="Arial" size="40.0" />
           </font>
        </TextField>
     </children>
  </HBox>
   </bottom>
   <center>
  <VBox prefHeight="200.0" prefWidth="100.0" BorderPane.alignment="CENTER">
     <children>
        <TextField editable="false" maxHeight="-Infinity" maxWidth="-Infinity" prefHeight="68.0" prefWidth="167.0" text="Your current goal" translateX="108.0">
           <font>
              <Font name="Arial" size="18.0" />
           </font>
        </TextField>
     </children>
  </VBox>
   </center>
</BorderPane>

最后是我犯的错误

Exception in Application stop method
Exception in thread "main" java.lang.RuntimeException: Exception in  Application stop method
at  com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:922)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$155(LauncherImpl.java:182)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NullPointerException
at sample.Main.stop(Main.java:59)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$163(LauncherImpl.java:882)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(PlatformImpl.java:326)
at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(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$148(WinApplication.java:191)

问题似乎主要在于代码end = finalGoal.getAccessibleText();。我也尝试过end = finalGoal.getText();但是它返回NullPointer,我也尝试过 end = String.valueOf(finalgoal.getText);返回值为“null”


共 (2) 个答案

  1. # 1 楼答案

    您需要从MainPageController类中获取对finalGoal变量的引用,而不是在Main类中定义具有相同名称的变量

  2. # 2 楼答案

    FXMLLoaderfinalGoal{}注入控制器类。它没有关于Main类的任何信息,也没有在那里注入Node

    因此,在调用stop时,默认值仍然被分配给fieldGoal字段

    解决方案

    1. 使用FXMLLoader.getController加载fxml文件后访问控制器。可以在控制器类中使用getter来访问值(fieldGoal)。或者
    2. 您还可以使用控制器工厂注册监听器以关闭,并删除一些代码重复(即加载FXML)
      这允许您将关闭处理程序放置在数据所在的位置:

      // factory for controllers also allowing to load fxmls and unregistering listeners
      public class Factory implements Callback<Class<?>, Object> {
      
          public Factory(List<InvalidationListener> listeners) {
              this.listeners = listeners;
          }
      
          private final List<InvalidationListener> listeners;
      
          @Override
          public Object call(Class<?> param) {
              Object result = null;
              try {
                  result = param.newInstance();
              } catch (InstantiationException | IllegalAccessException ex) {
                  Logger.getLogger(Factory.class.getName()).log(Level.SEVERE, null, ex);
                  throw new RuntimeException("Could not create instance of "+param.getName(), ex);
              }
      
              if (result instanceof ShutdownObserver) {
                  InvalidationListener listener = ((ShutdownObserver) result).getObserver();
                  if (listener != null) {
                      listeners.add(listener);
                  }
              }
      
              if (result instanceof FactoryAccessController) {
                  ((FactoryAccessController) result).setFactory(this);
              }
      
              return result;
          }
      
          public void removeShutdownListener(InvalidationListener listener) {
              listeners.remove(listener);
          }
      
          public <T> T loadFXML(URL url) throws IOException {
              if (url == null) {
                  throw new IllegalArgumentException();
              }
              FXMLLoader loader = new FXMLLoader(url);
              loader.setControllerFactory(this);
              return loader.load();
          }
      
      }
      
      public interface ShutdownObserver {
      
          InvalidationListener getObserver();
      
      }
      
      public class FactoryAccessController {
      
          private Factory factory;
      
          void setFactory(Factory factory) {
              this.factory = factory;
          }
      
          public Factory getFactory() {
              return factory;
          }
      
      }
      
      public class MainPageController extends FactoryAccessController implements ShutdownObserver {
      
          // keep reference to listener in case it should be removed
          private final InvalidationListener listener = o -> {
              // write data from fieldGoal to file
          };
      
          @Override
          public InvalidationListener getObserver() {
              return listener;
          }
      }
      
      private final List<InvalidationListener> shutdownListeners = new ArrayList<>();
      private final Factory factory = new Factory(shutdownListeners);
      
      @Override
      public void start(Stage primaryStage) throws IOException {
          primaryStage.setTitle("Money Saver Program");
          File f = new File("Goal.txt");
          Scene scene;
      
          if (f.exists()) {
              Parent root = factory.loadFXML(getClass().getResource("MainPage.fxml"));
              scene = new Scene(root, 600, 400);
          } else {
              boolean bool = f.createNewFile();
              Parent root = factory.loadFXML(getClass().getResource("OpeningPage.fxml"));
              scene = new Scene(root, 638, 400);
          }
      
          primaryStage.setScene(scene);
          primaryStage.show();
      }
      
      @Override
      public void stop() throws Exception {
          for (InvalidationListener listener : shutdownListeners) {
              try {
                  listener.invalidated(null);
              } catch (Exception ex) {
                  Logger.getLogger(getClass().getName())
                          .log(Level.WARNING,
                                  MessageFormat.format("Shutdown listener {0} yielded exception.", listener),
                                  ex);
              }
          }
      }
      

    另见Passing Parameters JavaFX FXML