【问题标题】:How to create multiple javafx controllers with different fxml files?如何使用不同的 fxml 文件创建多个 javafx 控制器?
【发布时间】:2013-10-20 22:58:49
【问题描述】:

我一直在查看一些博客和其他 stackoverflow 问题,但我没有看到我的问题的直接答案。我正在创建一个 javafx gui 客户端,我想让我的菜单栏成为一个 fxml 中的一个控制器,然后我希望内容区域是其他 fxml 文件。登录屏幕将是一个 fxml,在登录屏幕之后将是应用程序的主要内容,这将是一个 fxml。我该怎么做呢?

我只是不想将登录名、菜单栏和主要内容的所有代码都放在同一个文件中。这是我正在处理的图像:

【问题讨论】:

  • 一些sample code使用一些问题答案中的概念。
  • 这里的另一个例子:link

标签: java controller javafx-2 javafx fxml


【解决方案1】:

通过将自定义 java 类用作 fx:root 和 fx:controller 的 FXML 文件,将 FXML 用作组件:http://docs.oracle.com/javafx/2/fxml_get_started/custom_control.htm

为此,您需要调用自定义 java 类 FXMLLoader 的构造函数,它将加载您的 FXML。 好处是改变了FXML加载组件的方式。

使用嵌套控制器通过 FXMLLoader 实例化组件的经典方法是:首先是 FXML,然后是每个部分的控制器。

使用这种技术是:首先是控制器,然后是每个组件的 FXML。而且您不会直接在 FXML 中加载 FXML,您将在 FXML 中导入您的自定义 java 类。

这是一个更好的抽象(在 FXML 中导入组件时无需知道组件是如何实现的),并且有助于重用代码,就像实现支持 FXML 的自定义小部件一样。要使您的组件可重用,请确保您的实现不与其他部分紧密耦合,或者使用 IOC 来做到这一点(例如,使用 Spring 与 JavaFX 集成)。这样,您就可以将组件导入应用程序的任何部分(就像 DateInput 小部件一样)而无需担心,并且不会重复代码。

在您的情况下,您将拥有:

public class MenuBox extends VBox {

@FXML
private LoginBox loginBox;

@FXML
private ProfilesBox profilesBox;

public MenuBox() {
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("menu.fxml"));
    fxmlLoader.setRoot(this);
    fxmlLoader.setController(this);
    try {
        fxmlLoader.load();
    } catch (IOException exception) {
        throw new RuntimeException(exception);
    }
}

public class LoginBox extends VBox {
public LoginBox() {
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("login.fxml"));
    fxmlLoader.setRoot(this);
    fxmlLoader.setController(this);
    try {
        fxmlLoader.load();
    } catch (IOException exception) {
        throw new RuntimeException(exception);
    }
}

public class ProfilesBox extends VBox {
public ProfilesBox() {
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("profiles.fxml"));
    fxmlLoader.setRoot(this);
    fxmlLoader.setController(this);
    try {
        fxmlLoader.load();
    } catch (IOException exception) {
        throw new RuntimeException(exception);
    }
}

您将在 menu.fxml 中导入 LoginBox 和 ProfilesBox 来管理页面的全局布局:

<?import com.foo.bar.LoginBox ?>
<?import com.foo.bar.ProfilesBox ?>
<fx:root type="javafx.scene.layout.VBox"
    xmlns:fx="http://javafx.com/fxml">

<!-- Stuff here to declare the menu bar-->

    <HBox>
       <ProfilesBox fx:id="profilesBox"/>
       <LoginBox fx:id="loginBox"/>
    </HBox>

</fx:root>

login.fxml 和profiles.fxml 只包含基本组件。

【讨论】:

  • 我有点理解你的意思,我只是不认为我得到了全貌。你有更详细的例子吗?
  • 并且可以创建自己的小部件(即 ProfilesBox 和 LoginBox)并将它们放在 fxml 文件中吗? login.fxml 和profiles.fxml 长什么样子?
  • 要添加到已经很好的示例,您只需确保将自定义控件导入 FXML。例如。 .
  • 除了这个答案,这篇文章还有帮助:javacodegeeks.com/2013/03/javafx-2-with-spring.html
【解决方案2】:
  1. 您可以include FXML documents 一个又一个 - 这应该有助于您分离设计逻辑

  2. 这意味着您可以拥有Nested Controllers - 每个文档一个。

从文档中,您现在可以设置代码,以便逻辑可以从根控制器中分离以及调用(如果需要)。

希望对您有所帮助。

【讨论】:

  • 我查看了嵌套控制器文档,如果我能看到包含 fxml 中的内容、主控制器初始化方法中的内容以及对话框控制器的外观,我认为会非常有帮助。我只是不明白细节是如何工作的。
【解决方案3】:

我需要一个具有类似要求的弹出窗口(对节点和布​​局进行更多控制)。

在完成建议后,我找到了一个可能有用的解决方案。

首先,我创建了第二个 fxml 文档和第二个控制器(在 NetBeans 中,New -> Empty FXML ... -> Use Java Controller -> Create New ...)。

一个小挑战是弄清楚如何在主控制器中构建舞台并将其连接到弹出控制器。

链接Passing Parameters JavaFX FXML 提供了一些非常好的见解和技术。

最终的代码是这样的(希望对大家有帮助):

// Anchor Pane from the popup
@FXML
AnchorPane anchorPanePopup;

@FXML
private void soneButtonAction(ActionEvent event) throws IOException {     
    Stage newStage = new Stage();
    AnchorPane anchorPanePopup = (AnchorPane) FXMLLoader.load(getClass().getResource("Popup_FXML.fxml"));
    Scene scene = new Scene(anchorPanePopup);
    newStage.setScene(scene);
    newStage.initModality(Modality.APPLICATION_MODAL);
    newStage.setTitle("Dialog Window");
    newStage.showAndWait();        
}

【讨论】:

    【解决方案4】:
    package javafxapplication11;
    import java.io.IOException;
    import java.net.URL;
    import java.util.ResourceBundle;
    import javafx.event.ActionEvent;
    import javafx.fxml.FXML;
    import javafx.fxml.FXMLLoader;
    import javafx.fxml.Initializable;
    import javafx.scene.Node;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.scene.control.Button;
    import javafx.scene.control.CheckBox;
    import javafx.stage.Stage;
    
    public class FXMLDocumentController implements Initializable {
    @FXML
    private CheckBox c1;
    
    @FXML
    private CheckBox c2;
    
    public void clicked1(ActionEvent e) throws IOException {
    Parent home_page_parent 
    =FXMLLoader.load(getClass().getResource("AddDcuFXML.fxml"));
     Scene home_page_scene = new Scene(home_page_parent);
     Stage app_stage = (Stage) ((Node) e.getSource()).getScene().getWindow();
      app_stage.hide(); //optional
      app_stage.setScene(home_page_scene);
      app_stage.show();
       }
       public void clicked2(ActionEvent e) throws IOException {
       Parent home_page_parent 
        =FXMLLoader.load(getClass().getResource("ViewDCU.fxml"));
       Scene home_page_scene = new Scene(home_page_parent);
       Stage app_stage = (Stage) ((Node) e.getSource()).getScene().getWindow();
        app_stage.hide(); //optional
          app_stage.setScene(home_page_scene);
             app_stage.show();
         }
          public void clicked3(ActionEvent e) throws IOException {
         Parent home_page_parent 
       =FXMLLoader.load(getClass().getResource("ViewDCU.fxml"));
        Scene home_page_scene = new Scene(home_page_parent);
        Stage app_stage = (Stage) ((Node) e.getSource()).getScene().getWindow();
         app_stage.hide(); //optional
         app_stage.setScene(home_page_scene);
         app_stage.show();
          }
         @Override
           public void initialize(URL arg0, ResourceBundle arg1) {
            // TODO Auto-generated method stub
               } 
                   }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-28
      • 2013-12-25
      • 2016-08-20
      相关资源
      最近更新 更多