web-dev-qa-db-ja.com

異なるfxmlファイルで複数のjavafxコントローラーを作成する方法は?

私はいくつかのブログやその他のstackoverflowの質問を見てきましたが、私の質問に対する直接的な答えは見当たりません。 javafx guiクライアントを作成しています。メニューバーを1つのfxmlの1つのコントローラーにしたいので、コンテンツ領域を追加のfxmlファイルにしたいです。ログイン画面が1つのfxmlになり、ログイン画面がアプリケーションのメインコンテンツになり、それが1つのfxmlになります。これを行うにはどうすればよいですか?

ログイン、メニューバー、メインコンテンツのすべてのコードを同じファイルに入れたくありません。これは私が取り組んでいるもののイメージです:

enter image description here

22
j will

FXMLファイルのfx:rootおよびfx:controllerとしてカスタムJavaクラスを使用して、FXMLをコンポーネントとして使用します。 http://docs.Oracle.com/javafx/2 /fxml_get_started/custom_control.htm

そのためには、FXMLをロードするカスタムJavaクラスFXMLLoaderのコンストラクターを呼び出す必要があります。利点は、FXMLがコンポーネントをロードする方法を変更することです。

ネストされたコントローラーを使用してFXMLLoaderを介してコンポーネントをインスタンス化する古典的な方法は、最初にFXML、次に各パーツのコントローラーです。

この手法では、最初にコントローラー、次に各コンポーネントのFXMLを使用します。また、FXMLにFXMLを直接ロードするのではなく、カスタムのJavaクラスをFXMLにインポートします。

これはより優れた抽象化であり(FXMLにコンポーネントをインポートするときにコンポーネントを実装する方法を知る必要はありません)、FXMLをサポートするカスタムウィジェットを実装するようなコードの再利用に役立ちます。コンポーネントを再利用可能にするには、実装が他の部分と密結合していないことを確認するか、IOCを使用してそうします(たとえば、JavaFXとのSpring統合)。このように、 (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には、基本的なコンポーネントのみが含まれています。

28
zenbeni
  1. FXML文書を含める 相互に含めることができます-これは、設計ロジックの分離に役立ちます。

  2. これは、 ネストされたコントローラー -各ドキュメントに1つを持つことができることを意味します。

ドキュメントから、ロジックを分離したり、必要に応じてルートコントローラーから呼び出したりできるようにコードを設定できるようになりました。

お役に立てば幸いです。

5
Harsha R

同様の要件を持つポップアップウィンドウが必要でした(ノードとレイアウトをより詳細に制御できます)。

推奨事項を順を追って検討した結果、役立つソリューションが見つかりました。

最初に、2番目のfxmlドキュメントと2番目のコントローラーを作成しました(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();        
}
1
rainer
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
           } 
               }
0
Laxmi