• JavaFx之不通过全局静态变量进行窗体通信


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

    肯定是有的。。。

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

     1 public class StageAndController<C, S> {
     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<MouseEvent> {
     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     @Override
    12     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)
  • 相关阅读:
    css
    团队介绍
    day4
    线段树懒标记
    P2014选课
    P2015
    扩展欧几里得(exgcd)求解不定方程/求逆元
    transform和tolower
    快读
    bzoj2118
  • 原文地址:https://www.cnblogs.com/wtzl/p/10610038.html
Copyright © 2020-2023  润新知