gpt4 book ai didi

model-view-controller - 具有多个 Controller 的 MVC

转载 作者:行者123 更新时间:2023-12-05 07:50:45 25 4
gpt4 key购买 nike

我对用 Java/JavaFX 制作应用程序感到疯狂。

我有一个包含更多 fxml 文件的项目,每个文件都有一个 Controller (就像这个例子 JavaFX TabPane - One controller for each tab )

这是主要的 fxml 文件 (screentab.fxml),包含多个 fx:include

<TabPane fx:id="tabPane" BorderPane.alignment="CENTER">
<tabs>
<Tab text="Studenti">
<content>
<fx:include fx:id="Studenti" source="tabStudenti.fxml" />
</content>
</Tab>
<Tab text="Percorsi &#10;formativi">
<content>
<fx:include fx:id="tabPercorsiFormativi" source="tabPercorsiFormativi.fxml" />
</content>
</Tab>
<Tab text="Calendario &#10;delle&#10;lezioni">
<content>
<fx:include fx:id="tabCalendario" source="tabCalendario.fxml" />
</content>
</Tab>
</tabs>
</TabPane>

它有效,但我认为模型有问题。

Main.java文件下面

public class Main extends Application {
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Manage your student");
Model model = new Model();
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("gui/screentab.fxml"));
BorderPane root = (BorderPane)loader.load();
SoftwareController controller = loader.getController();
controller.setModel(model);
Scene scene = new Scene(root,1000,600);
scene.getStylesheets().add(getClass().getResource("gui/stylesheet1.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}

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

这是主 Controller (SoftwareController.java),方法是 setModel();

public class SoftwareController {

private Model model;

@FXML private TabPane tabPane;

@FXML private tabCalendarioController tabCalendarioController;
@FXML private tabPercorsiFormativiController tabPercorsiFormativiController;
@FXML private tabStudentiController tabStudentiController;


public void setModel(Model model) {
this.model = model;
}

@FXML
void initialize() {
assert tabPane != null : "fx:id=\"tabPane\" was not injected: check your FXML file 'screentab.fxml'.";
tabStudentiController.init(this);
tabCalendarioController.init(this);
tabPercorsiFormativiController.init(this);
}

}

模型 调用DAO 并包含从多个 Controller 调用的所有方法。

public class Model {

StudentiDAO dao = new StudentiDAO();
List<Studente> elencoStudenti = new ArrayList<Studente>();

public List<Studente> elencaStudenti(){
elencoStudenti= dao.listaStudenti();
return elencoStudenti;

}
}

这是调用模型方法的 Controller 之一。

public class tabStudentiController {
private SoftwareController main;
private Model model;

@FXML
private Button btnElencoStudenti;

@FXML
public void doVisualizzaStudenti(ActionEvent event) {

model.elencaStudenti();

txtStudenti.appendText("Elenco studenti: \n");
for(Studente s: lista ){

txtStudenti.appendText(s.getStud_NOME()+ " "+ s.getStud_COGNOME()+ "\n");
}

}

public void setModel(Model model) {
this.model = model ;
}

public void init(SoftwareController softwareController) {
main = softwareController;

}


@FXML
void initialize() {
assert tabPane != null : "fx:id=\"tabPane\" was not injected: check your FXML file 'screentab.fxml'.";
assert tabStudenti != null : "fx:id=\"tabStudenti\" was not injected: check your FXML file 'screentab.fxml'.";
}

}

问题:当我按下启动事件的按钮时 doVisualizzaStudenti 我有这个错误:

Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at javafx.fxml.FXMLLoader$MethodHandler.invoke(Unknown Source)
at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(Unknown Source)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(Unknown Source)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(Unknown Source)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
at com.sun.javafx.event.EventUtil.fireEventImpl(Unknown Source)
at com.sun.javafx.event.EventUtil.fireEvent(Unknown Source)
at javafx.event.Event.fireEvent(Unknown Source)
at javafx.scene.Node.fireEvent(Unknown Source)
at javafx.scene.control.Button.fire(Unknown Source)
at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(Unknown Source)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(Unknown Source)
at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(Unknown Source)
at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(Unknown Source)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(Unknown Source)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(Unknown Source)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(Unknown Source)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)


at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(Unknown Source)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(Unknown Source)
at com.sun.javafx.event.EventUtil.fireEventImpl(Unknown Source)
at com.sun.javafx.event.EventUtil.fireEvent(Unknown Source)
at javafx.event.Event.fireEvent(Unknown Source)
at javafx.scene.Scene$MouseHandler.process(Unknown Source)
at javafx.scene.Scene$MouseHandler.access$1500(Unknown Source)
at javafx.scene.Scene.impl_processMouseEvent(Unknown Source)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Unknown Source)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(Unknown Source)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(Unknown Source)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(Unknown Source)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(Unknown Source)
at com.sun.glass.ui.View.handleMouseEvent(Unknown Source)
at com.sun.glass.ui.View.notifyMouse(Unknown Source)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$148(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at sun.reflect.misc.Trampoline.invoke(Unknown Source)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at sun.reflect.misc.MethodUtil.invoke(Unknown Source)
... 57 more
Caused by: java.lang.NullPointerException
at software.tabStudentiController.doVisualizzaStudenti(tabStudentiController.java:36)
... 66 more

tabStudentiController.java:36model.elencaStudenti() 所在的行。

我哪里做错了?请帮助我,抱歉我的英语不好!

我用回调更改了 main,并在每个嵌套 Controller 中添加了 setModel()。但是现在我有这个错误:

`javafx.fxml.LoadException: 
/C:/software/gui/screentab.fxml
at javafx.fxml.FXMLLoader.constructLoadException(Unknown Source)
at javafx.fxml.FXMLLoader.loadImpl(Unknown Source)
at javafx.fxml.FXMLLoader.loadImpl(Unknown Source)
at javafx.fxml.FXMLLoader.load(Unknown Source)
at software.Main.start(Main.java:43)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$null$173(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(Unknown Source)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(Unknown Source)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$148(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at sun.reflect.misc.Trampoline.invoke(Unknown Source)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at sun.reflect.misc.MethodUtil.invoke(Unknown Source)
... 13 more
Caused by: java.lang.NullPointerException
at software.SoftwareController.initialize(SoftwareController.java:42)
... 22 more`

Main.java:43 是行 BorderPane root = (BorderPane)loader.load() 和 SoftwareController.java:42 是:tabStudentiController.init(this);

我又错了什么?

最佳答案

我在任何地方都没有看到您为“嵌套 Controller ”(例如 tabStudentiController)调用 setModel(...)。由于您从未初始化模型,因此您会在 model.elencaStudenti() 处遇到空指针异常。

当您在 SoftwareController 上设置模型时,您可能想要初始化每个嵌套 Controller 的模型:

public class SoftwareController {

private Model model;

@FXML private TabPane tabPane;

@FXML private tabCalendarioController tabCalendarioController;
@FXML private tabPercorsiFormativiController tabPercorsiFormativiController;
@FXML private tabStudentiController tabStudentiController;


public void setModel(Model model) {
this.model = model;
tabStduentiController.setModel(model);
tabCalendarioController.setModel(model);
tabPercorsiFormativiController.setModel(model);
}

@FXML
void initialize() {
assert tabPane != null : "fx:id=\"tabPane\" was not injected: check your FXML file 'screentab.fxml'.";
tabStudentiController.init(this);
tabCalendarioController.init(this);
tabPercorsiFormativiController.init(this);
}

}

另一种方法

也许更简洁的方法是让所有 Controller 类都将对模型的引用作为构造函数参数。这样,您就可以保证每个 Controller 在创建时都有一个模型实例:

public class SoftwareController {

private Model model;

@FXML private TabPane tabPane;

@FXML private tabCalendarioController tabCalendarioController;
@FXML private tabPercorsiFormativiController tabPercorsiFormativiController;
@FXML private tabStudentiController tabStudentiController;

public SoftwareController(Model model) {
this.model = model ;
}

@FXML
void initialize() {
assert tabPane != null : "fx:id=\"tabPane\" was not injected: check your FXML file 'screentab.fxml'.";
tabStudentiController.init(this);
tabCalendarioController.init(this);
tabPercorsiFormativiController.init(this);
}

}

public class tabStudentiController {
private SoftwareController main;
private Model model;

@FXML
private Button btnElencoStudenti;

public tabStudentiController(Model model) {
this.model = model ;
}

@FXML
public void doVisualizzaStudenti(ActionEvent event) {

model.elencaStudenti();

txtStudenti.appendText("Elenco studenti: \n");
for(Studente s: lista ){

txtStudenti.appendText(s.getStud_NOME()+ " "+ s.getStud_COGNOME()+ "\n");
}

}


public void init(SoftwareController softwareController) {
main = softwareController;

}


@FXML
void initialize() {
assert tabPane != null : "fx:id=\"tabPane\" was not injected: check your FXML file 'screentab.fxml'.";
assert tabStudenti != null : "fx:id=\"tabStudenti\" was not injected: check your FXML file 'screentab.fxml'.";
}

}

其他 Controller 也是如此。

默认情况下,FXMLLoader 调用 Controller 类的默认(无参数)构造函数来创建 Controller 实例。由于您不再拥有这样的构造函数,因此您需要告诉 FXMLLoader 如何创建 Controller 实例,您可以使用 Controller 工厂来完成:

public class Main extends Application {
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Manage your student");
Model model = new Model();

// the controller factory is just a function mapping a Class
// to a controller instance:

Callback<Class<?>, Object> controllerFactory = type -> {
try {
for (Constructor<?> c : type.getConstructors()) {
// look for a constructor taking a single parameter of type Model:
if (c.getParameterCount()==1 && c.getParameterTypes()[0]==Model.class) {
return c.newInstance(model);
}
}
// no suitable constructor found, just use default:
return type.newInstance();
} catch (Exception e) {
throw new RuntimeException(e);
}
};

try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("gui/screentab.fxml"));
loader.setControllerFactory(controllerFactory);
BorderPane root = (BorderPane)loader.load();
Scene scene = new Scene(root,1000,600);
scene.getStylesheets().add(getClass().getResource("gui/stylesheet1.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}

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

关于model-view-controller - 具有多个 Controller 的 MVC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35856668/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com