我有: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");
}
正如您所看到的,我在通过initialize方法加载根之后,在所有声明的字段(FXML-ID' S ARE BOUND!)上附加文本。听起来不错,但是我得到了一个NullPointerException。
明确指出事情: - 我已经将fxml-id绑定到相应的组件。 - 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
我没有在其他地方称它为btw。
修改 这是设置应用程序初始化。
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");
}
}
这是主要应用程序 公共类ApplicationLauncher扩展了Application {
/**
* 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());
答案 0 :(得分:1)
在与@SnakeDoc讨论了很长时间之后,我们终于设法解决了这个问题。
对于遇到同样问题的人:
new Settings().start(new Scene());
这样做。由于start方法基本上可以完成所有操作(加载FXML等),因此只需要那行代码。
如果您仍然遇到困难,请确保FXID与要连接的实例的变量名相同。
答案 1 :(得分:0)
这是嵌入在主应用程序控制器中的一些逻辑的示例:
// 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());
}
}
在此示例中,所有这些逻辑都在您的主控制器类中。按下Button toggleWebView;
按钮后,它会调用handleToggleWebView()
方法(在FXML中设置为onAction
)。如果它尚未构建,则反过来加载新窗口,然后显示或隐藏它。新窗口有自己的FXML文件,它有自己的控制器,然后用于处理按钮点击事件等...仅适用于该窗口。