JavaFX 无法编辑文本

JavaFX can't edit text

我有:2 个 FXML 文件和 2 个控制器。每个 FXML 都合并了控制器。这是打开新 FXML 的代码(虽然真正的 fxml 是 运行 它会打开另一个)

try {
            Parent root = FXMLLoader.load(getClass().getResource(
                    "settings.fxml"));
         Stage stage = new Stage();
         stage.setScene(new Scene(root));  
         stage.centerOnScreen();
         stage.show();
        } catch (Exception e) {
            e.printStackTrace();
            Logger.logCrash("ApplicationScene", e);
        }

这是打开的 FXML 文件的控制器

    @FXML
    public TextField destination;
    @FXML
    public TextArea view;
    @FXML
    public TextArea point;


    public void initialize() {
        destination.appendText("LOL");
        view.appendText("LAA");
        point.appendText("LOWKAPF");
    }

如您所见,在通过初始化方法加载根后,我在所有声明的字段(FXML-ID 已绑定!)上附加文本。听起来不错,但我收到 NullPointerException。

明确指出: - 我已经将 fxml-ids 绑定到它们相应的组件。 - FXML 文件被正确加载(root 被正确加载,否则初始化方法不会工作)

这与静态访问无关。即使没有静态访问,这也不起作用。

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

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

<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="373.0" prefWidth="518.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="removed">
   <children>
      <TextField fx:id="destination" layoutX="14.0" layoutY="19.0" prefHeight="25.0" prefWidth="464.0" promptText="Destination of the files" text="ie.: C:\" />
      <Text layoutX="14.0" layoutY="57.0" strokeType="OUTSIDE" strokeWidth="0.0" text="moo" wrappingWidth="464.0" />
      <TextArea fx:id="point" layoutX="14.0" layoutY="76.0" prefHeight="42.0" prefWidth="464.0" promptText="HI/>
      <Text layoutX="14.0" layoutY="131.0" strokeType="OUTSIDE" strokeWidth="0.0" text="meow" wrappingWidth="464.0" />
      <TextArea fx:id="view" layoutX="14.0" layoutY="135.0" prefHeight="42.0" prefWidth="464.0" promptText="HI" />
      <Text layoutX="14.0" layoutY="191.0" strokeType="OUTSIDE" strokeWidth="0.0" text="m00" wrappingWidth="464.0" />
      <Button layoutX="220.0" layoutY="269.0" mnemonicParsing="false" onAction="#initialize" text="Default" />
   </children>
</AnchorPane>

哦。好的,所以,我所做的是:

    package com.engine.application.content;

import com.engine.Logger;

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

public class Settings extends Application {

    public static void start() {
        Application.launch();
    }
    @Override
    public void start(Stage primaryStage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource(
                "settings.fxml"));
        Scene scene = new Scene(root);
        setStageProperties(primaryStage, scene);

    }

    /**
     * Sets the properties of the application
     * 
     * @param stage
     *            the stage's properties to set
     * @param scene
     *            the scene's properties to set
     */
    private void setStageProperties(Stage stage, Scene scene) {
        stage.setScene(scene);
        stage.setTitle("Test");
        stage.centerOnScreen();
        stage.setResizable(true);
        stage.show();
        Logger.log("Launcher", "Set stage properties");
    }

}

那我打电话
Application.start() 单击按钮时

这是结果:

Caused by: java.lang.IllegalStateException: Application launch must not be called more than once
    at com.sun.javafx.application.LauncherImpl.launchApplication(Unknown Source)
    at com.sun.javafx.application.LauncherImpl.launchApplication(Unknown Source)
    at javafx.application.Application.launch(Unknown Source)
    at xxx.Settings.start(Settings.java:14)
    at xxx.openMenu(ApplicationScene.java:43)
    ... 56 more

顺便说一句,我不会在其他地方称呼它。

编辑: 这是设置应用程序初始化。

public class Settings extends Application {

public static void main(String[] args) {
    launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
    Parent root = FXMLLoader.load(getClass().getResource(
            "settings.fxml"));
    Scene scene = new Scene(root);
    setStageProperties(primaryStage, scene);
    System.out.println("YAY");

}

/**
 * Sets the properties of the application
 * 
 * @param stage
 *            the stage's properties to set
 * @param scene
 *            the scene's properties to set
 */
private void setStageProperties(Stage stage, Scene scene) {
    stage.setScene(scene);
    stage.setTitle("Test");
    stage.centerOnScreen();
    stage.setResizable(true);
    ApplicationScene.settingsMenu = stage;
    Logger.log("Launcher", "Set stage properties");
}

}

这是主应用程序 public class ApplicationLauncher 扩展应用程序 {

/**
 * The main method
 * 
 * @param args
 *            the arguments given upon start
 */
public static void main(String args[]) {
    launch(args);
}

@Override
public void start(Stage stage) throws Exception {
    Logger.log("Launcher", "Starting up..");
    Parent root = FXMLLoader.load(getClass().getResource(
            "ah.fxml"));
    Directory directory = new Directory();
//  Logger.logError("LOL", "ERROR! LOLOLOL L /n LOL \n LOL LOL");
    Scene scene = new Scene(root);
    directory.createFolder();
    setStageProperties(stage, scene);
    Settings.main(null);
    Logger.log("Launcher", "Application started up!");
}

/**
 * Sets the properties of the application
 * 
 * @param stage
 *            the stage's properties to set
 * @param scene
 *            the scene's properties to set
 */
private void setStageProperties(Stage stage, Scene scene) {
    stage.setScene(scene);
    stage.setTitle("Test");
    stage.centerOnScreen();
    stage.setResizable(true);
    stage.show();
    Logger.log("Launcher", "Set stage properties");
}

}

结果:

Caused by: java.lang.IllegalStateException: Application launch must not be called more than once

没有别的地方叫它。 (顺便说一句。做 Settings.main(null); 与 Settings.launch(); 相同 lol)

重新思考概念后

做到了:

new Settings().start(new Scene());

这是主应用程序控制器中嵌入的一些逻辑示例:

// somewhere in the declarations for the controller class
private Parent webViewRoot;
private Stage webViewStage;
private Scene webViewScene;
private Path webViewFXML;

// somewhere in the logic section of the controller class
public void handleToggleWebView(final ActionEvent event) {
    initWebView();
    if (toggleWebView.isSelected()) {
        webViewStage.show();
    } else {
        webViewStage.close();
    }
}

private void initWebView() {
    if (webViewFXML == null) {
        webViewFXML = Paths.get(ConfigurationManager.ProdFeature.getHomeDirectory() 
                + File.separator + "resources" + File.separator + "WebView.fxml");
    }
    if (webViewRoot == null) {
        try {
            final FXMLLoader fxmlloader = new FXMLLoader(webViewFXML.toUri().toURL());
            fxmlloader.setRoot(webViewRoot);
            fxmlloader.setController(WebViewController.getInstance());
            webViewRoot = fxmlloader.load();
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            final Dialog exceptionDialog = new Dialog.Builder(DialogType.EXCEPTION)
            .setTitle("ERROR").setHeaderText("Failed to load WebView FXML.")
            .setException(e).build();
            exceptionDialog.showAndWait();
            return;
        }
    }
    if (webViewScene == null) {
        webViewScene = new Scene(webViewRoot);
    }
    if (webViewStage == null) {
        webViewStage = new Stage();
        try {
            // add icon
            Path icon = Paths.get(ConfigurationManager.ProdFeature.getHomeDirectory() 
                    + File.separator + "resources" + File.separator + "logo.png");
            webViewStage.getIcons().add(new Image(icon.toUri().toURL().toExternalForm()));
        } catch (Exception e) {
            // ignore
        }

        StringBuilder title = new StringBuilder();
        title.append(ConfigurationManager.ProdFeature.getString("prodfeature.program.name"));
        title.append(" WebView | version ");
        title.append(ConfigurationManager.ProdFeature.getString("prodfeature.program.version"));
        webViewStage.setTitle(title.toString());
        webViewStage.setScene(webViewScene);
        webViewStage.setOnCloseRequest(new EventHandler<WindowEvent>() {
            @Override
            public void handle(final WindowEvent we) {
                we.consume();
                toggleWebView.setSelected(false);
                webViewStage.close();
            }
        });
        webViewStage.initOwner(productTitleLabel.getParent().getScene().getWindow());
    }
}

在此示例中,所有这些逻辑都在您的主控制器中 class。当按下 Button toggleWebView; 按钮时,它会调用 handleToggleWebView() 方法(在 FXML 中设置为 onAction)。这反过来加载新的 window(如果尚未构建),然后显示或隐藏它。新的 window 有它自己的 FXML 文件和它自己的控制器,然后用于处理按钮点击事件等...仅 window。

经过与@SnakeDoc 的长期讨论,我们终于解决了它。

遇到同样问题的人:

new Settings().start(new Scene());

这样就可以了。由于 start 方法基本上完成了所有事情(加载 FXML 等),因此只需要那行代码。

如果您仍然遇到困难,请确保 FXID 与要连接的实例的变量名相同。