2016-12-22 8 views
0

나는 각자가 된 뷰를 나타내는 두 개의 FXML 문서를 검색,의 그들 View1View2을 부르 자, 나는이 TabPane 내부에 각각 별도의 Tab 하나, (Tab1Tab2)을 배치했다. 자바 FX : 노드

지금 View1Controller1에 나는 Tab2Tab1에서 내 TabPaneselectedItem 전환됩니다 이벤트가 있습니다. 제 질문은 내 TabPane에 액세스 할 수있는 방법입니다. Controller1

일반적으로 액세스 할 수 있습니다. Javafx에 특정 Node을 어떻게 검색합니까?

편집 뷰 1

<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"/> 

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 개월 만에 사무실로 걸어 말할 때 "고객은, 탭 창을 좋아하는 것을로 대체하지 않는다는 것입니다 만 보여줍니다 한 번에 한 화면 씩 "모든 것을 적절하게 분리 할 수 ​​있으므로 변경하기가 매우 쉽습니다. (메인 뷰와 컨트롤러 만 변경하면됩니다. 다른 뷰 또는 컨트롤러는 전혀 변경되지 않습니다.) 다른 모든 컨트롤러에 탭 패널을 노출 한 경우 액세스 한 모든 장소를 찾아야합니다 그것은 그러한 변화를 일으키는 것입니다.

+0

JavaFX는 일부 측면에서 부족할 수도 있지만, IMHO는 MVC 모델을 사용하도록 강제하는 것이 가장 좋습니다. – m0skit0

+0

매우 인상적입니다 –

+0

@ m0skit0 예 (MVC/MVP/MVVM/등 중 하나 이상). 큰 그림 디자인은 세부 사항 중 일부가 약간 조정될 수 있다고하더라도 매우 좋습니다. 그것은 장기적으로 좋은 징후 일 것입니다. –