我正在创建JAVA FX应用程序。是否有可能让控制器已经在JavaFX应用程序中打开窗口。例如,我有Application的mainScreen,但是当我打开其他modalWindow输入数据,最后输入所有数据并单击“保存”按钮时。应该不显示ModalWindow,并且应该刷新mainScreen。我想通过调用子控制器来调用它,而从子控制器中调用它。但是这样做的时候我会出错,任何其他建议都会有用。
Exception in thread "JavaFX Application Thread" java.lang.IllegalStateException: Location is not set.
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2428)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2403)
at controllers.ExitDialogController.setLocaleToSave(ExitDialogController.java:92)
at controllers.AddDialogDepatureController.lambda$onClick$4(AddDialogDepatureController.java:221)
at controllers.AddDialogDepatureController$$Lambda$359/1446130991.handle(Unknown Source)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Node.fireEvent(Node.java:8216)
at javafx.scene.control.Button.fire(Button.java:185)
at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89)
at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
我的ChildController类
if(new HttpRequests().departPost(jsonObject))
{
info.setStyle("-fx-text-fill: green");
info.setText(myResourceBundle.getString("infoSave"));
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(getClass().getResource(FxmlViews.MainScreen.mainSc));
try
{
AnchorPane frame = fxmlLoader.load();
MainScreenController mainScreenController = (MainScreenController)fxmlLoader.getController();
mainScreenController.updateTable(myResourceBundle);
} catch (IOException e)
{
e.printStackTrace();
}
success = true;
}
答案 0 :(得分:0)
当我查看Stacktrace时,发现它并没有抱怨创建控制器。
它抱怨它不能首先加载FXML文件。它以某种方式找不到。因此它中止了-在它甚至到达要加载控制器的行之前(那行看起来还不错):
线程“ JavaFX Application Thread”中的异常 java.lang.IllegalStateException:未设置位置。 在javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2428) 在javafx.fxml.FXMLLoader.load(FXMLLoader.java:2403)
您可能想更仔细地查看“ FxmlViews.MainScreen.mainSc”的值。这很可能指向错误的路径。
两次装入控制器的示例:
String filename = "yourfxm.fxml";
FXMLLoader loader = new FXMLLoader(FXMLLoader.class.getResource(filename));
var node = loader.load();
var controller = loader.getController();
loader = new FXMLLoader(FXMLLoader.class.getResource(filename));
node = loader.load();
controller = loader.getController();
答案 1 :(得分:0)
JavaFX API仅允许您通过FXMLLoader.load()方法获取控件上的引用。使用FXMLLoader的实例,您可以执行以下操作(就像您已经做过的:-)):
FXMLLoader loader = new FXMLLoader();
loader.setLocation(getClass().getResource("MainForm.fxml"));
Parent root = (Parent) loader.load();
// as soon as the load() method has been invoked, the scene graph and the
// controller instance are availlable:
MainFormController controller = loader.getController();
这意味着:
如果以后需要的话,最好在控制器上保留有关构建时间/加载时间的引用。
更好:如果需要从子控制器中访问父控制器,请三思。这可能是警告,说明应用程序的架构有问题。
如果您确实需要子控制器与父控制器之间的通信,则最好将其“事件驱动”,即在子控制器中创建可观察的属性,并让父控制器侦听更改。
希望有帮助...
答案 2 :(得分:0)
这是一个从FXML文件中替换自身的控制器。 它很简单,只有一个按钮触发了替换,但确实如此。 舞台,场景和控制器存储为静态变量,以将所有内容保存在一个文件中。您可以将它们存储在其他任何位置。
public class RootReplacingItselfController implements Initializable {
public static RootReplacingItselfController controller = null;
public static Stage stage = null;
public static Scene scene = null;
public final static String filename = "/fxml/RootReplacingItself.fxml";
@Override
public void initialize(URL url, ResourceBundle rb) {
// TODO
}
@FXML
private void replaceme(ActionEvent event) {
try {
//open an additional modal Dialog
FXMLLoader dialogloader = new FXMLLoader(FXMLLoader.class.getResource(filename));
Stage dialog = new Stage();
dialog.setScene(new Scene(dialogloader.load()));
dialog.initModality(Modality.APPLICATION_MODAL);
dialog.initOwner(stage);
dialog.showAndWait();
//When the dialog is done replace myself:
FXMLLoader loader = new FXMLLoader(FXMLLoader.class.getResource(filename));
Parent node = loader.load();
controller= loader.getController();
scene.setRoot(node);
} catch (IOException ex) {}
}
public static RootReplacingItselfController create(){
try {
FXMLLoader loader = new FXMLLoader(FXMLLoader.class.getResource(filename));
Parent node = loader.load();
controller= loader.getController();
scene = new Scene(node);
stage = new Stage();
stage.setScene(scene);
stage.show();
return controller;
} catch (IOException ex) {}
return controller;
}
}
还有FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane id="AnchorPane" prefHeight="151.0" prefWidth="232.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/11.0.1" fx:controller="fxControls.RootReplacingItselfController">
<children>
<Button layoutX="76.0" layoutY="76.0" mnemonicParsing="false" onAction="#replaceme" text="replaceme" />
</children>
</AnchorPane>
我对其进行了编辑,因此该按钮另外打开了一个模态子对话框。现在,再次使用相同的fxml创建此对话框。 在该模式对话框中,您可以再次按下replaceme按钮并打开另一个模式对话框,然后再次从该对话框中打开,依此类推。
每当关闭模式对话框时(完成对话框),将替换根控制器。对于所有已创建的孩子。
因此,您现在也有了该模式对话框。对话框关闭后,根将被替换(并且始终是根)。当然,您也可以为对话框使用其他FXM。
FWIW:就我个人而言,到目前为止,我无法想象一个真正的项目会选择这样的方法,因为当它与应用程序的其他部分进行交互时,很可能会引起头痛。但这不是我决定的。