博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JavaFx之不通过全局静态变量进行窗体通信
阅读量:6072 次
发布时间:2019-06-20

本文共 6762 字,大约阅读时间需要 22 分钟。

百度了n多窗体通信,,,总是通过定义全局静态变量进行传值通信。。我个人不喜欢一个controller里写满所有的布局(这样显得臃肿,但是组件传值方便)。有没有另外的办法进行模块化并且可以传值呢。。

肯定是有的。。。

1.定义一个泛型类接收Controller对象与Stage对象

 

1 public class StageAndController
{ 2 private C controller; 3 private S stage; 4 5 public StageAndController(C controller, S stage) { 6 this.controller = controller; 7 this.stage = stage; 8 } 9 public StageAndController(C controller) {10 this.controller = controller;11 }12 13 public C getController() {14 return controller;15 }16 17 public void setController(C controller) {18 this.controller = controller;19 }20 21 public S getStage() {22 return stage;23 }24 25 public void setStage(S stage) {26 this.stage = stage;27 }28 }

 

这里之所以返回两个对象,,首先每个controller都对应一个打开的布局窗体,controller用来传值、赋值、初始化操作,stage本身需要调用show()才显示,,所以定义此类

 

2.封装 打开一个窗体或者动态加载一个Node

1 public static StageAndController addMenu(final Pane pane, final String fxmlName, Object controller) { 2         URL location = AddOperation.class.getResource("/fxml/" + fxmlName); 3         FXMLLoader fxmlLoader = new FXMLLoader(); 4         fxmlLoader.setLocation(location); 5         fxmlLoader.setBuilderFactory(new JavaFXBuilderFactory()); 6         try { 7             Node node = fxmlLoader.load();//返回Node对象  Node是布局顶级父类,再之上就是Object,所有此处可以加载一个布局添加到父级中 8             pane.getChildren().add(node);//Node添加到父级布局 9             controller = fxmlLoader.getController();//获取加载布局的Contrller对象10         } catch (IOException e) {11             e.printStackTrace();12         }13         return new StageAndController(controller);//返回controller实例14     }
//pane->需要添加node的父级Pane及Pane子类对象  fxmlName-->自定义的布局文件   Object-->需要实例化的Controller

这里我的用法是动态增加一排菜单栏,使用了到了controller传值作用,用法如下:

StageAndController controller = AddOperation.addMenu(operation, "read_item.fxml", ReadCardController.class);        readCardController = (ReadCardController) controller.getController();

向父级窗体暴露了一个Controller实例对象,就可以进行父窗体向子组件传值,初始化。

-------------------------------------------------------------------------------------------------------

1  public static StageAndController newDialog(String fxmlName, String title, Object controller) { 2         URL location = OpenDialog.class.getResource("/fxml/" + fxmlName); 3         FXMLLoader fxmlLoader = new FXMLLoader(); 4         fxmlLoader.setLocation(location); 5         fxmlLoader.setBuilderFactory(new JavaFXBuilderFactory()); 6         Stage stage = new Stage(); 7         try { 8             Pane dialogPane = fxmlLoader.load(); 9             stage.setScene(new Scene(dialogPane));10             stage.initModality(Modality.APPLICATION_MODAL);11             stage.initStyle(StageStyle.DECORATED);12             stage.setResizable(false);13             if (title != null) {14                 stage.setTitle(title);15             }16             controller = fxmlLoader.getController();17 18         } catch (IOException e) {19             e.printStackTrace();20         }21         return new StageAndController(controller, stage);

此处同理,加载的是一个窗体布局,同时设置模态化(本身未关闭,父级窗体不可点击)、动态标题,,,,,返回一个Controller与Stage对象,,,用法如下:

StageAndController stageAndController = OpenDialog.newDialog("connectDevice.fxml", "连接", ConnectDevice.class);        ConnectDevice controller = (ConnectDevice) stageAndController.getController();        Stage stage = (Stage) stageAndController.getStage();        controller.str= str;        controller.init();        stage.show();

窗体显示之前父窗体向子窗体传值或者做一些初始化。 这样模块化布局传值也变得简单好维护。

-------------------------------------------------------------------------------------------------------

嫌弃自带窗体风格太丑,,可以往下看。。

自定义Stage窗体布局(State设置透明时):

public static StageAndController customDialog(String fxmlName, Object controller, Pane pane, String css) {        URL location = OpenDialog.class.getResource("/fxml/" + fxmlName);        FXMLLoader fxmlLoader = new FXMLLoader();        fxmlLoader.setLocation(location);        fxmlLoader.setBuilderFactory(new JavaFXBuilderFactory());        Stage stage = new Stage();        try {            pane = fxmlLoader.load();            Background background = new Background(new BackgroundFill(Paint.valueOf("#EFEFEF"), new CornerRadii(15), new Insets(0)));            pane.setBackground(background);            pane.setBorder(new Border(new BorderStroke(Color.valueOf("#0096C9"), BorderStrokeStyle.SOLID, new CornerRadii(15), new BorderWidths(2))));            Scene scene = new Scene(pane);            if (css != null) {                scene.getStylesheets().add(OpenDialog.class.getResource("/css/" + css).toExternalForm());            }            scene.setFill(Paint.valueOf("#FFFFFF00"));//设置场景透明            stage.initModality(Modality.APPLICATION_MODAL);            stage.initStyle(StageStyle.TRANSPARENT);            stage.setResizable(false);            stage.setScene(scene);            controller = fxmlLoader.getController();        } catch (IOException e) {            e.printStackTrace();        }        return new StageAndController(controller, stage);    }

用法差不多,加了一个自定义加载css样式,可以按需更改,,不过自定义时,,窗体头部拖动就不可用,下面贴出解决方案:

1 public class DragListener implements EventHandler
{ 2 3 private double xOffset = 0; 4 private double yOffset = 0; 5 private final Stage stage; 6 7 public DragListener(Stage stage) { 8 this.stage = stage; 9 }10 11 @Override12 public void handle(MouseEvent event) {13 event.consume();14 if (event.getEventType() == MouseEvent.MOUSE_PRESSED) {15 xOffset = event.getSceneX();16 yOffset = event.getSceneY();17 } else if (event.getEventType() == MouseEvent.MOUSE_DRAGGED) {18 stage.setX(event.getScreenX() - xOffset);19 if(event.getScreenY() - yOffset < 0) {20 stage.setY(0);21 }else {22 stage.setY(event.getScreenY() - yOffset);23 }24 }25 }26 27 public void enableDrag(Node node) {28 node.setOnMousePressed(this);29 node.setOnMouseDragged(this);30 }31 }

用法如下:

1   StageAndController stageAndController = OpenDialog.customDialog("connectDevice_cus.fxml",ConnectDevice.class,new Pane(),null);2         ConnectDevice controller = (ConnectDevice) stageAndController.getController();3         Stage stage = (Stage) stageAndController.getStage();4         new DragListener(stage).enableDrag(controller.title);//自定义窗口时设置拖动监听   此处controller.title是我自定义窗体标题栏的HBox对象5         controller.stage = stage;6         controller.init();7         stage.show();

这样就可以愉快的使用自定义弹窗了。。。。

-------------------------------------------------------------------------------------------------------

不喜勿喷!!!! 欢迎进群学习交流(927465926)

转载于:https://www.cnblogs.com/wtzl/p/10610038.html

你可能感兴趣的文章
小孩的linux
查看>>
CSS3 transforms 3D翻开
查看>>
java基础---->正则表达式
查看>>
2.2013/06/13_log(n)+1
查看>>
关于加载iframe时进度条不消失的问题
查看>>
poj 3984迷宫问题【广搜】
查看>>
oracle ORA-01840:输入值对于日期格式不够长
查看>>
python基础知识~logger模块
查看>>
SIP入门(二):建立SIPserver
查看>>
Servlet3.0的异步
查看>>
WebService连接postgresql( 失败尝试)
查看>>
从头认识java-13.11 对照数组与泛型容器,观察类型擦除给泛型容器带来什么问题?...
查看>>
Python-MacOSX下SIP引起的pip权限问题解决方案(非取消SIP机制)
查看>>
从MFQ方法到需求分析
查看>>
android.view.WindowManager$BadTokenException: Unable to add window
查看>>
HDU5012:Dice(bfs模板)
查看>>
iphone openssh
查看>>
Linux下MEncoder的编译
查看>>
Xamarin使用ListView开启分组视图Cell数据展示bug处理
查看>>
Javascript中闭包(Closure)的探索(一)-基本概念
查看>>