Javafx - 将当前在textfield中的值保存到外部txt文件中

时间:2016-07-26 06:47:19

标签: java javafx textfield fxml

我正在为学校创建一个节省金钱的计划,该计划的目标是您希望保存多少,计算您在一周内赚取的金额以及根据您花多少钱和保存来编辑您的目标。我目前正试图在文本字段中获得该目标,以便在程序关闭时保存在txt文件中。但无论我如何尝试修复它,我都会得到一个NullPointerException或者textfield的值保存为“null”

以下是主要内容(我尝试在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 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

FXMLLoaderfinalGoal Node注入控制器类。它没有与Main课程相关的任何信息,也没有注入Node

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

解决方案

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

    // 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);
            }
        }
    }
    
  3. 另见Passing Parameters JavaFX FXML