我的问题很简单。
我有3个控制器:
我试图告诉Controller
内部,按下按钮时,请更改Controller1
中的标签文字。使用MainController
作为中间人。当我要求它改变到新场景同时还希望传递有关标签的信息时出现问题。
第17行的NullPointerExecption,Controller类(main.setLabel("abc");)
我没有MainController
的单独FXML文件。但是我有一个单独的项目,我在使用MainController
和FXML时运行代码,但是我必须使用Tabpane并创建单独的选项卡,这不是我正在寻找的。
MainController.class
package sample;
import javafx.fxml.FXML;
public class MainController {
@FXML Controller controller1;
@FXML Controller2 controller2;
private void initialize() {
System.out.println("Application started");
controller1.init(this);
controller2.init(this);
}
public void setLabel(String text) {
System.out.println("Setting text..");
controller2.label123.setText(text);
}
}
Controller.class
package sample;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.control.Button;
import java.io.IOException;
public class Controller {
@FXML private MainController main;
@FXML private Button buttonSend;
@FXML private void buttonClicked(ActionEvent event) throws IOException {
main.setLabel("abc");
System.out.println("Button clicked.");
FXMLLoader loader = new FXMLLoader(getClass().getResource("sample2.fxml"));
Parent root = loader.load();
buttonSend.getScene().setRoot(root);
}
public void init(MainController mainController) {
main = mainController;
}
}
Controller2.class
package sample;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
public class Controller2 {
private MainController main;
@FXML public Label label123;
public void init(MainController mainController) {
main = mainController;
}
}
sample.fxml (适用于Controller.class)
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.text.Font?>
<GridPane alignment="center" hgap="10" vgap="10" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.60" fx:controller="sample.Controller">
<children>
<AnchorPane prefHeight="200.0" prefWidth="200.0">
<children>
<Button fx:id="buttonSend" layoutX="61.0" layoutY="81.0" mnemonicParsing="false" onAction="#buttonClicked" text="Button">
<font>
<Font size="18.0" />
</font>
</Button>
</children>
</AnchorPane>
</children>
</GridPane>
sample2.fxml (对于Controller2.class)
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller2">
<children>
<Label fx:id="label123" layoutX="250.0" layoutY="168.0" text="Label">
<font>
<Font size="43.0" />
</font>
</Label>
</children>
</AnchorPane>
答案 0 :(得分:0)
不知何故,您需要将MainController
的实例传递给控制器。
在这种情况下,我建议使用MainController
作为工厂或创建一个&#34;知道&#34;关于MainController
。您可以将有关控制器的信息传递给MainController
方法中的init
实例:
public interface InitializableController {
public void init(MainController mainController);
}
public class MainController {
private Controller controller1;
public void setController1(Controller controller) {
this.controller1 = controller;
}
private Controller2 controller2;
public void setController2(Controller2 controller) {
this.controller2 = controller;
}
public void setLabel(String text) {
System.out.println("Setting text..");
controller2.label123.setText(text);
}
public <T> T loadFXML(URL url) throws IOException {
FXMLLoader loader = new FXMLLoader(url);
T result = loader.load();
// call init, if there is a controller implementing InitializableController
Object controller = loader.getController();
if (controller instanceof InitializableController) {
((InitializableController) controller).init(this);
}
return result;
}
}
public class Controller implements InitializableController {
...
@FXML private void buttonClicked(ActionEvent event) throws IOException {
System.out.println("Button clicked.");
Parent root = main.load(getClass().getResource("sample2.fxml"));
main.setLabel("abc");
buttonSend.getScene().setRoot(root);
}
@Override
public void init(MainController mainController) {
main = mainController;
mainController.setController(this);
}
}
public class Controller2 implements InitializableController {
// private MainController main;
@FXML public Label label123;
@Override
public void init(MainController mainController) {
// main = mainController;
mainController.setController2(this);
}
}
请确保同时使用MainController.load
方法加载第一个fxml。
BTW:我不建议让其他类直接访问其中一个控制器的字段。您可以将数据移至MainController
类,并在StringProperty
方法中添加text
label123
属性init
可以绑定到MainController
类。这种方式Controller2
无需了解{{1}}的内部结构,因此更易于维护。