简体   繁体   English

JavaFX - 许多静态FXML控制器

[英]JavaFX - Many Static FXML Controllers

A JavaFX application exists and the application is starting from the Main.class file which extends Application : 存在JavaFX应用程序,应用程序从Main.class文件开始,该文件extends Application

  public class Main extends Application {

    /**
     * Keep a reference to the main Stage
     */
    public static Stage                 stage;
    /**
     * MainScene Controller
     */
    public static MainScene             mainSceneController;
    /**
     * The Capture Window of the application
     */
    public static CaptureWindow         captureWindowController;
    /**
     * Settings Scene Controller
     */
    public static SettingsController    settingsController;

    @Override
    public void start(Stage primary) throws Exception {

        stage = primary;
        ..........

        // CaptureWindow
        FXMLLoader loader1 = new FXMLLoader(getClass().getResource("/fxml/CaptureWindow.fxml"));
        loader1.load();
        captureWindowController = loader1.getController();

        // MainScene
        mainSceneController = new MainScene();

        .........   
    }

  }

Description 描述

As you can see above I have 3 FXMLControllers (one is reusable[ extends StackPane ],others not).I have declared all of them static cause i want to access variables from one FXMLController from the other FXMLControllers .I use this strategy every time I use JavaFX and I don't think is good... 正如你在上面看到的,我有3个FXMLControllers (一个是可重用的[ extends StackPane ],其他没有)。我已经声明所有这些都是静态的,因为我想从一个FXMLController从其他FXMLControllers访问变量。我每次都使用这个策略使用JavaFX ,我觉得不好......

How I can change the code below so I can access variables or methods of one FXMLController from other FXMLController ? 我如何更改下面的代码,以便从其他FXMLController访问一个FXMLController变量或方法? Is that possible without using static keyword? 没有使用static关键字可以吗?

Consider that the Controllers are represented from different classes which can be in different packages. 考虑控制器由不同的类表示,这些类可以位于不同的包中。


Also before writing this question I had a look Static @FXML variables in FXML Controller 在写这个问题之前,我在FXML Controller中查看了Static @FXML变量

Actually the answer for this question seems a little bit complicated it has to do with MVC pattern and it's evolution until now.We will use MVP Pattern. 实际上这个问题的答案看起来有点复杂,它与MVC模式和它的演化有关,直到现在。我们将使用MVP模式。

After a long discussion i got a link on this website http://martinfowler.com/eaaDev/uiArchs.html defining the historical evolution of the different patterns used from the old ages of Smalltalk until now. 经过长时间的讨论后,我在这个网站http://martinfowler.com/eaaDev/uiArchs.html上找到了一个链接,定义了从Smalltalk的旧时代到现在使用的不同模式的历史演变。


The actually solution is using Model Viewer Presenter Pattern(MVP) which can be visually described using these images: 实际的解决方案是使用Model Viewer Presenter Pattern(MVP) ,可以使用这些图像直观地描述:

在此输入图像描述

在此输入图像描述

For more you can read( http://www.wildcrest.com/Potel/Portfolio/mvp.pdf ) 欲了解更多信息,请阅读( http://www.wildcrest.com/Potel/Portfolio/mvp.pdf


For an example on JavaFX have a look on James_D answer here ( Applying MVC With JavaFx ) 有关JavaFX的示例,请查看James_D答案( 使用JavaFx应用MVC


Last but not least have a look at the comments here : 最后但并非最不重要的是看看这里的评论:

Finally: 最后:

If anything is inaccurate feel free to edit. 如果有任何不准确的地方,请随时编辑。

I think you are not supposed to declare @FXML annotated attributes with the static keyword. 我认为您不应该使用static关键字声明@FXML带注释的属性。 See this GitHub project on how you should do it. 请参阅此GitHub项目 ,了解如何执行此操作。 Like that you instantiate a controller only when it is needed, and your app will be stateless. 就像你只在需要时实例化控制器一样,你的应用程序将是无状态的。

JavaFx is mostly composed of set of [well designed] tools but unfortunately by itself does not provide a good framework for creating complex UI designs eg MVC/MVP patterns, view flows and actions on multiple controllers, So you have to rely on third-party application frameworks for those for example: JavaFx主要由一组[精心设计]工具组成,但不幸的是,它本身并没有为创建复杂的UI设计提供良好的框架,例如MVC / MVP模式,视图流和多个控制器上的操作,所以你必须依赖第三方应用程序框架,例如:

In my opinion none of them are widely used or mature enough to be considered a de facto standard but using them is encouraged. 在我看来,没有一个被广泛使用或成熟到足以被视为事实上的标准,但鼓励使用它们。


Example Using DataFx 使用DataFx的示例

DataFx uses a concept named Flow to associate views sharing a flow of events (and possibly data) among themselves. DataFx使用名为Flow的概念来关联共享事件流(以及可能的数据)的视图。 By using Flow combined with EventSystem you can define and access methods on other controllers and assign custom event listeners to various events associated with JavaFx Nodes in different controllers sharing a flow. 通过将Flow与EventSystem结合使用,您可以定义和访问其他控制器上的方法,并将自定义事件侦听器分配给与共享流的不同控制器中的JavaFx节点关联的各种事件。

Here is an example from DataFx samples which represents two separate sender and receiver views with distinct FXML files and controllers: 以下是DataFx示例中的示例,它表示具有不同FXML文件和控制器的两个独立的发送者和接收者视图:

在此输入图像描述

public class EventSystemDemo extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {

    HBox box = new HBox();
    box.setSpacing(12);
    box.setPadding(new Insets(12));
    box.setFillHeight(true);
    box.setAlignment(Pos.CENTER);

    Flow senderFlow = new Flow(ProducerController.class);
    box.getChildren().add(senderFlow.start());

    Flow receiverFlow = new Flow(ReceiverController.class);
    box.getChildren().add(receiverFlow.start());

    primaryStage.setScene(new Scene(box));
    primaryStage.show();

    }

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

Sender view controller: 发件人视图控制器:

@ViewController("producer.fxml")
public class ProducerController {

    @FXML
    @EventTrigger()
    private Button sendButton;

    @FXML
    private TextField textField;

    @EventProducer("test-message")
    private String getMessage() {
        return textField.getText();
    }

}

Receiver view controller: 接收器视图控制器:

@ViewController("receiver.fxml")
public class ReceiverController {

    @FXML
    private Label messageLabel;

    @OnEvent("test-message")
    private void onNewChatMessage(Event<String> e) {
        messageLabel.setText(e.getContent());
    }
}

Sender View: 发件人查看:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.text.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>

<VBox alignment="TOP_CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" spacing="12.0" style="-fx-border-color: darkgrey; -fx-border-width: 2;" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <Label text="Sender">
         <font>
            <Font name="System Bold" size="24.0" />
         </font>
      </Label>
      <TextField fx:id="textField" />
      <Button fx:id="sendButton" mnemonicParsing="false" text="send" />
   </children>
   <padding>
      <Insets bottom="12.0" left="12.0" right="12.0" top="12.0" />
   </padding>
</VBox>

Receiver View: 接收者视图:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.text.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>

<VBox alignment="TOP_CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" spacing="12.0" style="-fx-border-color: darkgrey; -fx-border-width: 2;" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
    <children>
        <Label text="Receiver">
         <font>
            <Font name="System Bold" size="24.0" />
         </font></Label>
      <Label fx:id="messageLabel" />
    </children>
    <padding>
        <Insets bottom="12.0" left="12.0" right="12.0" top="12.0" />
    </padding>
</VBox>

For further reading: 进一步阅读:

http://www.oracle.com/technetwork/java/javafx/community/3rd-party-1844355.html http://www.oracle.com/technetwork/java/javafx/community/3rd-party-1844355.html

http://www.guigarage.com/2015/02/quick-overview-datafx-mvc-flow-api/ http://www.guigarage.com/2015/02/quick-overview-datafx-mvc-flow-api/

http://www.guigarage.com/2014/05/datafx-8-0-tutorials/ http://www.guigarage.com/2014/05/datafx-8-0-tutorials/

http://jacpfx.org/2014/11/03/JacpFX_DataFX_a_perfect_match.html http://jacpfx.org/2014/11/03/JacpFX_DataFX_a_perfect_match.html

Passing Parameters JavaFX FXML 传递参数JavaFX FXML

You can implement your own controller factory so you would be able of creating your own controllers context. 您可以实现自己的控制器工厂,这样您就可以创建自己的控制器上下文。

I have used spring with javaFX, and I have implemented my own controllers factory using spring, in that way you can inject one controller in other (you shouldn't need it as those connections should be on the model) 我使用spring和javaFX,并且我已经使用spring实现了我自己的控制器工厂,这样你可以在另一个中注入一个控制器(你不应该需要它,因为那些连接应该在模型上)

If you want to try spring with Java fx: How to wire multiple fxml controllers using spring dependency-injection? 如果你想用Java fx尝试spring: 如何使用spring依赖注入连接多个fxml控制器?

Definitely you should use an Application Framework that will help you to structure your code. 当然,您应该使用可帮助您构建代码的应用程序框架。

If you want to try JRebirth, just cut your application in 4 parts: 如果您想尝试JRebirth,只需将您的应用程序分为4个部分:

  • MainModel composed by: MainModel组成:
    • MainSceneModel MainSceneModel
    • CaptureWindowModel CaptureWindowModel
    • SettingsModel SettingsModel

You can access to one from anyone by using getModel(Model.class) or send async message using sendWave(Wave). 您可以使用getModel(Model.class)访问任何人,也可以使用sendWave(Wave)发送异步消息。

MainModel can use innerComponent to tightly link child-model to it. MainModel可以使用innerComponent将子模型紧密链接到它。

It's pretty simple to use, if you are interested in I can prototype you a sample app just let me know. 它使用起来非常简单,如果你对我感兴趣,我可以为你做一个示例应用程序原型让我知道。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM