【问题标题】:To initialize or to not initialize JavaFX TextField [duplicate]初始化或不初始化JavaFX TextField [重复]
【发布时间】:2018-11-24 13:50:01
【问题描述】:

我有一个 JavaFX 应用程序,它具有显示FileChooser 的功能。我只想获取所选文件的路径并将文本字段设置为应用程序中的该路径。我需要重复使用此功能 4 次。每次,我将TextField ID 传递给它说它是null 的函数,然后得到NullPointerException。我尝试了几种不同的解决方案,说要为它创建一个initialize(),但这也不起作用。

多个来源表示初始化文本字段对象如:

TextField global_dataset_1 = new TextField(); 

然后一些消息来源说不要这样做,而只是参考 .fxml ID;这就是我最初想要做的......我尝试了上面的第一个,方法是在开头声明它并将其包装成@Override initialize()。都没有奏效。我在 .fxml 文件中设置了 ID。

我也看过:http://tutorials.jenkov.com/javafx/filechooser.htmlhttps://examples.javacodegeeks.com/desktop-java/javafx/fxml/javafx-fxml-controller-example/https://github.com/mwilchek/Restaurant-Gift-Card-Lookup-App/blob/master/src/controller/NewAccountController.java

以下是我所拥有的:

Main.java

package views;

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

public class Main extends Application {

    public static Stage primaryStage = new Stage();

    @Override
    public void start(Stage primaryStage) throws IOException{
        Parent root = FXMLLoader.load(getClass().getResource("Main.fxml"));
        primaryStage.setTitle("Configuration Manager");
        primaryStage.setScene(new Scene(root, 1100, 700));
        primaryStage.show();
    }

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

FxmlController.java

package controller;

import javafx.beans.property.SimpleObjectProperty;
import javafx.fxml.FXML;
import javafx.scene.control.Accordion;
import javafx.scene.control.TextField;
import javafx.scene.layout.AnchorPane;
import javafx.stage.FileChooser;
import java.io.File;

import static views.Main.primaryStage;


public class FxmlController {

    @FXML
    Accordion mainList;
    @FXML
    AnchorPane AnchorPane1;

    //TextFields are all set to NULL ERROR
    @FXML
    TextField global_dataset_1;
    @FXML
    TextField global_dataset_2;
    @FXML
    TextField global_dataset_3;
    @FXML
    TextField global_dataset_4;

    public void fileChooser1() {
        fileChooser(global_dataset_1);
    }

    public void fileChooser2() {
        fileChooser(global_dataset_2);
    }

    public void fileChooser3() {
        fileChooser(global_dataset_3);
    }

    public void fileChooser4() {
        fileChooser(global_dataset_4);
    }

    public FxmlController(){

    }

    // Error: For some reason won't pass TextField Object here...
    public void fileChooser(TextField field) {
        FileChooser fileChooser = new FileChooser();
        fileChooser.setTitle("Select Global Dataset");
        fileChooser.getExtensionFilters().addAll(
            new FileChooser.ExtensionFilter("CSV Files", "*.csv"),
            new FileChooser.ExtensionFilter("All Files", "*.*"));
        File selectedFile = fileChooser.showOpenDialog(primaryStage);
        field.appendText(selectedFile.getPath());
    }

Main.fxml

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

<?import java.lang.String?>
<?import javafx.collections.FXCollections?>
<?import javafx.scene.control.Accordion?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.control.SeparatorMenuItem?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.TitledPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>

<VBox prefHeight="700.0" prefWidth="1100.0" style="-fx-background-color: white;" stylesheets="@bootstrap3.css" xmlns="http://javafx.com/javafx/8.0.121" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controller.FxmlController">
  <children>
    <MenuBar style="-fx-background-color: #2176ff;" styleClass="context-menu" stylesheets="@bootstrap3.css" >
      <menus>
        <Menu mnemonicParsing="false" styleClass="menu-item" text="File">
          <items>
            <MenuItem mnemonicParsing="false" text="New" />
            <MenuItem mnemonicParsing="false" text="Open…" />
            <Menu mnemonicParsing="false" text="Open Recent" />
            <SeparatorMenuItem mnemonicParsing="false" />
            <MenuItem mnemonicParsing="false" text="Close" />
            <MenuItem mnemonicParsing="false" text="Save" />
            <MenuItem mnemonicParsing="false" text="Save As…" />
            <MenuItem mnemonicParsing="false" text="Revert" />
            <SeparatorMenuItem mnemonicParsing="false" />
            <MenuItem mnemonicParsing="false" text="Preferences…" />
            <SeparatorMenuItem mnemonicParsing="false" />
            <MenuItem mnemonicParsing="false" text="Quit" />
          </items>
        </Menu>
        <Menu mnemonicParsing="false" text="Help">
          <items>
            <MenuItem mnemonicParsing="false" text="About" />
          </items>
        </Menu>
      </menus>
    </MenuBar>
      <SplitPane dividerPositions="0.5, 0.5, 0.5" prefHeight="659.0" prefWidth="1100.0" >
         <items>
            <Accordion id="mainList" prefWidth="384.0">
              <panes>
                <TitledPane animated="false" styleClass="primary" stylesheets="@bootstrap3.css" text="Global Configurations">
                  <content>
                    <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="52.0" prefWidth="393.0" >
                           <children>
                              <Label layoutX="14.0" layoutY="15.0" prefHeight="41.0" prefWidth="93.0" text="Year:">
                                 <font>
                                    <Font size="18.0" />
                                 </font>
                              </Label>
                               <ChoiceBox id="year" layoutX="405.0" layoutY="21.0" prefWidth="116.0" style="-fx-background-color: #2176ff;" styleClass="primary" stylesheets="@bootstrap3.css" value="2018">
                                   <items>
                                       <FXCollections fx:factory="observableArrayList">
                                           <String fx:value="2018" />
                                           <String fx:value="2019" />
                                           <String fx:value="2020" />
                                           <String fx:value="2021" />
                                           <String fx:value="2022" />
                                       </FXCollections>
                                   </items>
                               </ChoiceBox>
                              <Label layoutX="14.0" layoutY="70.0" text="Run Name:">
                                 <font>
                                    <Font size="18.0" />
                                 </font>
                              </Label>
                              <Separator layoutX="-3.0" layoutY="54.0" prefHeight="13.0" prefWidth="537.0" />
                              <TextField id="run_name" layoutX="298.0" layoutY="68.0" prefHeight="32.0" prefWidth="225.0" promptText="Run Name" style="-fx-background-color: #2176ff; -fx-text-fill: white;" styleClass="primary" stylesheets="@bootstrap3.css">
                                 <font>
                                    <Font size="14.0" />
                                 </font>
                              </TextField>
                              <Separator layoutX="-2.0" layoutY="109.0" prefHeight="13.0" prefWidth="537.0" />
                              <Label layoutX="14.0" layoutY="122.0" prefHeight="35.0" prefWidth="140.0" text="Global Datasets" underline="true">
                                 <font>
                                    <Font name="Century" size="18.0" />
                                 </font>
                              </Label>
                              <Label layoutX="14.0" layoutY="160.0" text="Dataset 1: ">
                                 <font>
                                    <Font size="18.0" />
                                 </font>
                              </Label>
                              <Label layoutX="14.0" layoutY="192.0" text="Dataset 2: ">
                                 <font>
                                    <Font size="18.0" />
                                 </font>
                              </Label>
                              <Label layoutX="14.0" layoutY="227.0" text="Dataset 3: ">
                                 <font>
                                    <Font size="18.0" />
                                 </font>
                              </Label>
                              <Label layoutX="14.0" layoutY="263.0" text="Dataset 4: ">
                                 <font>
                                    <Font size="18.0" />
                                 </font>
                              </Label>
                              <TextField id="global_dataset_1" cache="true" layoutX="111.0" layoutY="158.0" prefWidth="379.0" promptText="Path to File" styleClass="primary" stylesheets="@bootstrap3.css" />
                              <Button layoutX="497.0" layoutY="157.0" mnemonicParsing="false" onMouseClicked="#fileChooser1" styleClass="primary" stylesheets="@bootstrap3.css" text="..." />
                              <TextField id="global_dataset_2" cache="true" layoutX="111.0" layoutY="191.0" prefWidth="379.0" promptText="Path to File" styleClass="primary" stylesheets="@bootstrap3.css" />
                              <TextField id="global_dataset_3" cache="true" layoutX="111.0" layoutY="227.0" prefWidth="379.0" promptText="Path to File" styleClass="primary" stylesheets="@bootstrap3.css" />
                              <TextField id="global_dataset_4" cache="true" layoutX="110.0" layoutY="263.0" prefWidth="379.0" promptText="Path to File" styleClass="primary" stylesheets="@bootstrap3.css" />
                              <Button layoutX="497.0" layoutY="192.0" mnemonicParsing="false" styleClass="primary" stylesheets="@bootstrap3.css" text="..." />
                              <Button layoutX="497.0" layoutY="226.0" mnemonicParsing="false" styleClass="primary" stylesheets="@bootstrap3.css" text="..." />
                              <Button layoutX="497.0" layoutY="262.0" mnemonicParsing="false" styleClass="primary" stylesheets="@bootstrap3.css" text="..." />
                           </children></AnchorPane>
                  </content>
                </TitledPane>
                <TitledPane animated="false" styleClass="primary" stylesheets="@bootstrap3.css" text="Annual 1">
                  <content>
                    <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
                  </content>
                </TitledPane>
                <TitledPane animated="false" styleClass="primary" stylesheets="@bootstrap3.css" text="Annual 2">
                  <content>
                    <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
                  </content>
                </TitledPane>
              </panes>
            </Accordion>
            <AnchorPane id="AnchorPane1" prefHeight="200.0" prefWidth="200.0" visible="true" />
            <AnchorPane id="AnchorPane2" prefHeight="200.0" prefWidth="200.0" visible="false" />
            <AnchorPane id="AnchorPane3" prefHeight="200.0" prefWidth="200.0" visible="false" />
         </items>
      </SplitPane>
  </children>
</VBox>

任何帮助将不胜感激!

【问题讨论】:

  • 拥有一个文本字段数组比拥有 4 个单独的文本字段更好/更灵活,所有这些文本字段都有自己的 fileChooser 方法。只需将您想要设置的所需文本字段对象的索引传递给方法,以便您可以执行类似fileChooser(int index){fileChooser(textFieldArray[index])} 的操作
  • 我可以将其实现为 fileChooser 的解决方法,但是,这些字段仍设置为 null。我不明白为什么当我在控制器中引用它们并将它们 ID 到 .fxml 文件中时......:-/

标签: java javafx


【解决方案1】:

您在构建 FXML 文件的方式上存在错误。在您的标签中,您需要使用fx:id 设置节点的ID,但您只需使用id

您的TextFields 应更改为:

<TextField fx:id="global_dataset_1" ...

附注:

您可能想要使用field.setText() 而不是appendText(),除非您的意图是允许他们选择多个文件并将它们全部列出在同一个文本字段中。

另外,在你的控制器类中,你应该将你的节点声明为private

@FXML
private TextField global_dataset_1;

最后,没有必要(或不推荐)将您的 primaryStage 共享为公共字段。另一种打开FileChooser 居中的方法是从控制器中声明的任何节点获取当前Window

File selectedFile = fileChooser.showOpenDialog(
                global_dataset_1.getScene().getWindow());

【讨论】:

  • 共享的甚至不是初级阶段。这是其他一些从未使用过的Stage。除了将它传递给showOpenDialog 方法。
  • 感谢 Zephyr 的建议,不幸的是,当我输入时,我的 IDE 显示“无法将 javafx.scene.control.TextField 设置为字段 'global_dataset_1' :-/
  • @fabian 哦,对。我错过了导入并误读了用法。不过,primaryStage 仍被声明为 public
  • @Programming_Noob 要么您的 IDE 错误(不太可能),要么在您进行更改时出现其他问题。如果您所做的只是将 FXML 中每个 TextFieldid 更改为 fx:id,那么您应该没有问题。
  • 是的,当它运行时我没有收到任何错误。我在 TextField 上收到 NullPointException 错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-09
  • 2022-11-30
  • 2022-01-22
  • 2016-06-23
  • 1970-01-01
  • 2011-02-15
  • 2013-02-10
相关资源
最近更新 更多