javafx中controller与fxml及参数传值-3
来自于: https://www.bilibili.com/video/BV1tt4y1W7nY?spm_id_from=333.788.videopod.sections&vd_source=137b7db2f57c3cb63d8af247fefc66e0
三、多controller,多stage通信与传值
将自己定义的通用页面文件加入scenebuilder,然后再其他页面中可以拖去使用
1、fxml文件合并到一个文件,通过file--import--fxml,如将center-view.fxml和bottom-view.fxml合并到main-view-import.fxml,
相当于内容复制操作。
先将borderPane用anchorPane包裹,然后file--import--fxml--center-view.fxml和bottom-view.fxml导入,
将center-view.xml拖到borderPane的center,将bottom-view.xml拖到borderPane的bottom,然后再解除包裹unwrap
import这种方式,不能实现多控制器处理,相当于一个独立页面。
2、fxml文件嵌入到一个文件,通过file--include--fxml,如将center-view.fxml和bottom-view.fxml包含到main-view-include.fxml,
相当于内容嵌入操作,main-view-include.fxml中加入的是对center-view.fxml和bottom-view.fxml引用。
include可以实现多控制器处理。main-view-include.fxml最终页面代码如下:
<BorderPane xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.wyrjgs.eventbus.fxcontroller.MainController">
<center>
<fx:include source="center-view.fxml" />
</center>
<bottom>
<fx:include source="bottom-view.fxml" />
</bottom>
</BorderPane>
方案一、通过控制器类成员属性调用其他控制器类
1、应用类
public class HelloApplication extends Application {
@Override
public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/main-view.fxml"));
Scene scene = new Scene(fxmlLoader.load());//创建场景, 320, 240
stage.setTitle("Hello!");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
2、模块引入类
module com.wyrjgs.multiplecontroller {
requires javafx.controls;
requires javafx.fxml;
opens com.wyrjgs.multiplecontroller to javafx.fxml;
exports com.wyrjgs.multiplecontroller;
exports com.wyrjgs.multiplecontroller.fxcontroller;
opens com.wyrjgs.multiplecontroller.fxcontroller to javafx.fxml;
}
3、主界面控制器类
public class MainController {
//@FXML//可以使用@FXML注解,也可以不使用@FXML注解
public Pane center;//fx:id="center" 该id名成必须和对应控制器名称前缀一致 CenterController,否则会报错,找不对象
//@FXML//可以使用@FXML注解,也可以不使用@FXML注解
public AnchorPane bottom;//fx:id="bottom" 该id名成必须和对应控制器名称前缀一致 BottomController,否则会报错,找不对象
@FXML
private Locale locale;
@FXML
ResourceBundle resourceBundle;
@FXML
CenterController centerController;//去掉私有方便调用,也可用get方法处理
@FXML
BottomController bottomController;//去掉私有方便调用,也可用get方法处理
@FXML
void initialize(){
centerController.setMainController(this);
bottomController.setMainController(this);
}
public MainController()
{
}
}
//不建议使用实现Initializable接口
//public class MainController implements Initializable {
// @Override
// public void initialize(URL url, ResourceBundle resourceBundle) {
//
// }
// }
4、中心控制器类
public class CenterController{
@FXML
private Locale locale;
@FXML
ResourceBundle resourceBundle;
@FXML
Rectangle rect;
@FXML
void initialize(){}
@FXML
MainController mainController;//private 去掉私有方便调用,也可用get方法处理
public void setMainController(MainController mainController) {
this.mainController = mainController;
}
@FXML
void onSendInfoAction() {
mainController.bottomController.labelInfo.setText("位置信息:"+rect.getLayoutX()+"\t"+rect.getLayoutY());
}
public CenterController() {
}
}
//不建议使用实现Initializable接口
//public class CenterController implements Initializable {
// @Override
// public void initialize(URL url, ResourceBundle resourceBundle) {
//
// }
// }
5、底部控制器类
public class BottomController {
@FXML
private Locale locale;
@FXML
ResourceBundle resourceBundle;
@FXML
Label labelInfo;//private 去掉私有方便调用,也可用get方法处理
@FXML
MainController mainController;//private 去掉私有方便调用,也可用get方法处理
public void setMainController(MainController mainController) {
this.mainController = mainController;
}
@FXML
void initialize(){}
@FXML
void onMoveDown(ActionEvent event) {
Rectangle rect = mainController.centerController.rect;
rect.setLayoutY(rect.getLayoutY()+5);
}
@FXML
void onMoveLeft(ActionEvent event) {
Rectangle rect = mainController.centerController.rect;
rect.setLayoutX(rect.getLayoutX()-5);
}
@FXML
void onMoveRight(ActionEvent event) {
Rectangle rect = mainController.centerController.rect;
rect.setLayoutX(rect.getLayoutX()+5);
}
@FXML
void onMoveUp(ActionEvent event) {
Rectangle rect = mainController.centerController.rect;
rect.setLayoutY(rect.getLayoutY()-5);
}
public BottomController() {
}
}
//不建议使用实现Initializable接口
//public class BottomController implements Initializable {
// @Override
// public void initialize(URL url, ResourceBundle resourceBundle) {
//
// }
// }
6、main-view.fxml
<BorderPane prefHeight="771.0" prefWidth="717.0" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.wyrjgs.multiplecontroller.fxcontroller.MainController">
<center>
<fx:include fx:id="center" source="center-view.fxml" />
<!-- fx:id="center" 该id名成必须和控制器名称前缀一致 CenterController,否则会报错,找不对象-->
</center>
<bottom>
<fx:include fx:id="bottom" source="bottom-view.fxml" />
<!-- fx:id="bottom" 该id名成必须和控制器名称前缀一致 BottomController,否则会报错,找不对象-->
</bottom>
</BorderPane>
7、center-view.fxml
<Pane prefHeight="505.0" prefWidth="607.0" style="-fx-border-color: #808080; -fx-border-width: 3;" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.wyrjgs.multiplecontroller.fxcontroller.CenterController">
<children>
<Rectangle fx:id="rect" arcHeight="5.0" arcWidth="5.0" fill="DODGERBLUE" height="52.0" layoutX="276.0" layoutY="227.0" stroke="BLACK" strokeType="INSIDE" width="55.0" />
<Button fx:id="sendBtn" layoutX="260.0" layoutY="461.0" mnemonicParsing="false" onAction="#onSendInfoAction" text="发送位置信息" />
</children>
</Pane>
8、bottom-view.fxml
<AnchorPane prefHeight="165.0" prefWidth="625.0" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.wyrjgs.multiplecontroller.fxcontroller.BottomController">
<children>
<Button layoutX="345.0" layoutY="74.0" mnemonicParsing="false" onAction="#onMoveRight" text="右" />
<Button layoutX="228.0" layoutY="74.0" mnemonicParsing="false" onAction="#onMoveLeft" text="左" />
<Button layoutX="288.0" layoutY="108.0" mnemonicParsing="false" onAction="#onMoveDown" text="下" />
<Button layoutX="288.0" layoutY="32.0" mnemonicParsing="false" onAction="#onMoveUp" text="上" />
<Label fx:id="labelInfo" layoutX="10.0" layoutY="144.0" prefHeight="15.0" prefWidth="557.0" text="位置信息" />
</children>
</AnchorPane>
9、需要注意:
<fx:include fx:id="center" source="center-view.fxml" />
<!-- fx:id="center" 该id名成必须和控制器名称前缀一致 CenterController,否则会报错,找不对象-->
<fx:include fx:id="bottom" source="bottom-view.fxml" />
<!-- fx:id="bottom" 该id名成必须和控制器名称前缀一致 BottomController,否则会报错,找不对象-->
方案二、统一管理类,管理控制器类,在管理类中每个控制器为静态成员
方案三、统一管理类,通过map管理控制器类,调用时获取并强转为该控制器类
方案二和方案三主要变化为,ControllerManage.java,MainCotroller.java,CenterController,BottomController.java,如下:
1、ControllerManage.java内容
/**
* 统一管理静态变量,方便获取控制器
* */
public class ControllerManager {
//私有构造方法,不允许外部创建ControllerManager对象,只能通过ControllerManager.mainController获取静态成员
private ControllerManager(){}
//方案2:把每个控制器提前定义在ControllerManager中,在控制器初始化方法中初始化控制器,然后在方法中调用相应控制器中对应成员等,缺点需要定义大量成员变量
public static MainController mainController;
public static CenterController centerController;
public static BottomController bottomController;
//方案3:把每个控制器都放在一个map中,通过key获取对应的控制器,在控制器初始化方法中将控制器添加到map中,然后在方法中调用相应控制器并强制转换为对应控制器中对应成员等
public static Map<String,Object> controllersMap = new HashMap<>();
}
2、MainCotroller.java内容
public class MainController {
//@FXML//可以使用@FXML注解,也可以不使用@FXML注解
public Pane center;//fx:id="center" 该id名成必须和对应控制器名称前缀一致 CenterController,否则会报错,找不对象
//@FXML//可以使用@FXML注解,也可以不使用@FXML注解
public AnchorPane bottom;//fx:id="bottom" 该id名成必须和对应控制器名称前缀一致 BottomController,否则会报错,找不对象
@FXML
private Locale locale;
@FXML
ResourceBundle resourceBundle;
@FXML
void initialize(){
//方案2:把每个控制器提前定义在ControllerManager中,在控制器初始化方法中初始化控制器,然后在方法中调用相应控制器中对应成员等,缺点需要定义大量成员变量
ControllerManager.mainController = this;
//方案3:把每个控制器都放在一个map中,通过key获取对应的控制器,在控制器初始化方法中将控制器添加到map中,然后在方法中调用相应控制器并强制转换为对应控制器中对应成员等
ControllerManager.controllersMap.put("mainController",this);
}
public MainController()
{
}
}
//不建议使用实现Initializable接口
//public class MainController implements Initializable {
// @Override
// public void initialize(URL url, ResourceBundle resourceBundle) {
//
// }
// }
3、CenterController内容
public class CenterController{
@FXML
private Locale locale;
@FXML
ResourceBundle resourceBundle;
@FXML
Rectangle rect;
@FXML
void initialize(){
//方案2:把每个控制器提前定义在ControllerManager中,在控制器初始化方法中初始化控制器,然后在方法中调用相应控制器中对应成员等
ControllerManager.centerController = this;
//方案3:把每个控制器都放在一个map中,通过key获取对应的控制器,在控制器初始化方法中将控制器添加到map中,然后在方法中调用相应控制器并强制转换为对应控制器中对应成员等
ControllerManager.controllersMap.put("centerController",this);
}
@FXML
void onSendInfoAction() {
//方案2:把每个控制器提前定义在ControllerManager中,在控制器初始化方法中初始化控制器,然后在方法中调用相应控制器中对应成员等
ControllerManager.bottomController.labelInfo.setText("位置信息:"+rect.getLayoutX()+"\t"+rect.getLayoutY());
//方案3:把每个控制器都放在一个map中,通过key获取对应的控制器,在控制器初始化方法中将控制器添加到map中,然后在方法中调用相应控制器并强制转换为对应控制器中对应成员等
BottomController bottomController = (BottomController) ControllerManager.controllersMap.get("bottomController");
bottomController.labelInfo.setText("位置信息:"+rect.getLayoutX()+"\t"+rect.getLayoutY());
}
public CenterController() {
}
}
//不建议使用实现Initializable接口
//public class CenterController implements Initializable {
// @Override
// public void initialize(URL url, ResourceBundle resourceBundle) {
//
// }
// }
4、BottomController.java内容
public class BottomController {
@FXML
private Locale locale;
@FXML
ResourceBundle resourceBundle;
@FXML
Label labelInfo;//private 去掉私有方便调用,也可用get方法处理
@FXML
void initialize(){
//方案2:把每个控制器提前定义在ControllerManager中,在控制器初始化方法中初始化控制器,然后在方法中调用相应控制器中对应成员等
ControllerManager.bottomController = this;
//方案3:把每个控制器都放在一个map中,通过key获取对应的控制器,在控制器初始化方法中将控制器添加到map中,然后在方法中调用相应控制器并强制转换为对应控制器中对应成员等
ControllerManager.controllersMap.put("bottomController",this);
}
@FXML
void onMoveDown(ActionEvent event) {
//方案2:把每个控制器提前定义在ControllerManager中,在控制器初始化方法中初始化控制器,然后在方法中调用相应控制器中对应成员等
Rectangle rect = ControllerManager.centerController.rect;
rect.setLayoutY(rect.getLayoutY()+5);
//方案3:把每个控制器都放在一个map中,通过key获取对应的控制器,在控制器初始化方法中将控制器添加到map中,然后在方法中调用相应控制器并强制转换为对应控制器中对应成员等
CenterController centerController =(CenterController)ControllerManager.controllersMap.get("centerController");
centerController.rect.setLayoutY(centerController.rect.getLayoutY()+5);
}
@FXML
void onMoveLeft(ActionEvent event) {
//方案2:把每个控制器提前定义在ControllerManager中,在控制器初始化方法中初始化控制器,然后在方法中调用相应控制器中对应成员等
Rectangle rect = ControllerManager.centerController.rect;
rect.setLayoutX(rect.getLayoutX()-5);
//方案3:把每个控制器都放在一个map中,通过key获取对应的控制器,在控制器初始化方法中将控制器添加到map中,然后在方法中调用相应控制器并强制转换为对应控制器中对应成员等
CenterController centerController =(CenterController)ControllerManager.controllersMap.get("centerController");
centerController.rect.setLayoutX(centerController.rect.getLayoutX()-5);
}
@FXML
void onMoveRight(ActionEvent event) {
//方案2:把每个控制器提前定义在ControllerManager中,在控制器初始化方法中初始化控制器,然后在方法中调用相应控制器中对应成员等
Rectangle rect = ControllerManager.centerController.rect;
rect.setLayoutX(rect.getLayoutX()+5);
//方案3:把每个控制器都放在一个map中,通过key获取对应的控制器,在控制器初始化方法中将控制器添加到map中,然后在方法中调用相应控制器并强制转换为对应控制器中对应成员等
CenterController centerController =(CenterController)ControllerManager.controllersMap.get("centerController");
centerController.rect.setLayoutX(centerController.rect.getLayoutX()+5);
}
@FXML
void onMoveUp(ActionEvent event) {
//方案2:把每个控制器提前定义在ControllerManager中,在控制器初始化方法中初始化控制器,然后在方法中调用相应控制器中对应成员等
Rectangle rect = ControllerManager.centerController.rect;
rect.setLayoutY(rect.getLayoutY()-5);
//方案3:把每个控制器都放在一个map中,通过key获取对应的控制器,在控制器初始化方法中将控制器添加到map中,然后在方法中调用相应控制器并强制转换为对应控制器中对应成员等
CenterController centerController =(CenterController)ControllerManager.controllersMap.get("centerController");
centerController.rect.setLayoutY(centerController.rect.getLayoutY()-5);
}
public BottomController() {
}
}
//不建议使用实现Initializable接口
//public class BottomController implements Initializable {
// @Override
// public void initialize(URL url, ResourceBundle resourceBundle) {
//
// }
// }