2016-12-22 3 views
0

私はそれぞれがビューを表す2つのFXML文書を持っているを取得し、のは彼らView1View2を呼びましょう、と私はTabPaneの内側にそれぞれ別々のTabで1、(Tab1Tab2)を配置しています。私はTab2Tab1から私のTabPaneselectedItemを切り替えますイベントを持っているView1Controller1で今のJavaFX:ノード

。私の質問は、私は一般的にController1

から私のTabPaneにアクセスする方法です。どのようにNodeJavafxに検索しますか?

編集 View1を

<VBox fx:controller="controllers.Controller1"> 
    <Button onAction="#openView2"/> 
</VBox> 

Controller1

public class Controller1{ 
    public void openView2(){ 
     //What should I do here 
    } 
} 

MAINVIEW

<TabPane fx:id="tabPane" fx:controller="controllers.MainController"/> 

メインコントローラ

public class MainController implements Initializable { 

@FXML 
public TabPane tabPane; 

@Override 
public void initialize(URL arg0, ResourceBundle arg1) { 
    try { 
     tabPane.getTabs().add(createView1Tab()); 
     tabPane.getTabs().add(createView2Tab()); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 

protected Tab createView1Tab() throws IOException { 
    Tab tab = new Tab(); 
    tab.setContent(FXMLLoader.load(getClass().getResource("/views/View1.fxml"))); 
    return tab; 
} 

protected Tab createView2Tab() throws IOException { 
    Tab tab = new Tab(); 
    tab.setContent(FXMLLoader.load(getClass().getResource("/views/View2.fxml"))); 
    return tab; 
} 
} 
+0

一般に、コントローラ内のあるビューから別のビューにアクセスすることはできません。代わりに、観測可能なデータを変更し、必要な場所でそれらのデータを観察してください。問題を示す[MCVE]で質問を編集することができれば、ここで実際の回答を提供する方が簡単です。 –

+0

編集していただきありがとうございますが、それを校正してタイプミスを修正できますか? 'openView1()'は 'openView2()'であるべきですか?MainViewの 'mainController'は' MainController'であると仮定していますか? –

答えて

2

ビューの現在の状態をカプセル化し、それぞれのコントローラと共有する「ビューモデル」を作成する必要があります。その後、メインコントローラからそれを観察し、それに応じて応答します。例えば

public class ApplicationState { 

    private final StringProperty currentViewName = new SimpleStringProperty(); 

    public StringProperty currentViewNameProperty() { 
     return currentViewName ; 
    } 

    public final String getCurrentViewName() { 
     return currentViewNameProperty().get(); 
    } 

    public final void setCurrentViewName(String viewName) { 
     currentViewNameProperty().set(viewName); 
    } 
} 

今、あなたが行うことができます(私もここにあなたの冗長反復コードを削除します)。

public class MainController implements Initializable { 

    @FXML 
    public TabPane tabPane; 

    private final ApplicationState appState = new ApplicationState(); 
    private final Map<String, Tab> views = new HashMap<>(); 

    @Override 
    public void initialize(URL arg0, ResourceBundle arg1) { 
     try { 
      tabPane.getTabs().add(createViewTab("View1", new Controller1(appState))); 
      tabPane.getTabs().add(createViewTab("View2", new Controller2(appState))); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     appState.currentViewNameProperty().addListener((obs, oldView, newView) -> 
      tabPane.getSelectionModel().select(views.get(newView))); 
     appState.setCurrentViewName("View1"); 
    } 

    protected Tab createViewTab(String viewName, Object controller) throws IOException { 
     Tab tab = new Tab(); 
     FXMLLoader loader = new FXMLLoader(getClass().getResource("/views/"+viewName+".fxml")); 
     loader.setController(controller); 
     tab.setContent(loader.load()); 
     views.put(viewName, tab); 
     return tab; 
    } 


} 

今、あなたのコントローラがちょうどしなければならない。

public class Controller1{ 

    private final ApplicationState appState ; 

    public Controller1(ApplicationState appState) { 
     this.appState = appState ; 
    } 

    public void openView2(){ 
     appState.setCurrentViewName("View2"); 
    } 
} 

コントローラには引数なしのコンストラクタがないので、コードでを設定しています。つまり、view1とview2のfxmlファイルからfx:controller属性を削除する必要があります。あなたのView1.fxmlは、次のようになります。

<VBox xmlns="..."> <!-- no fx:controller here --> 
    <Button onAction="#openView2"/> 
</VBox> 

この設計の利点は、あなたの上司は8ヶ月であなたのオフィスに歩くと、顧客は、タブペインを好きではない」と言うとき、それだけのショー何かに置き換えることです一度に1つの画面を表示する "ことができます。すべてが適切に分離されているので、そのような変更は非常に簡単です。 (メインビューとそのコントローラーを変更するだけで、他のビューやコントローラーはまったく変更されません)。タブペインを他のすべてのコントローラーに公開した場合、アクセスしたすべての場所を見つける必要がありますそれはそのような変更を加えることです。

+0

JavaFXはいくつかの面で欠けているかもしれませんが、IMHOはMVCモデルを使用するように何らかの理由で強制しています。 – m0skit0

+0

非常に印象的 –

+0

@ m0skit0はい(MVC/MVP/MVVM /などの少なくとも1つ)たとえ細部のいくつかが微調整を使用することができたとしても、大きな絵のデザインはとても良いです。それはおそらく長期的には良い兆候でしょう。 –

関連する問題