2016-11-16 6 views
0

Нужна ваша помощь! Это может быть больше перспективы дизайна, но я использую этот шаблон во всем моем приложении, поэтому хотел получить представление.JavaFX. Доступ к данным одного контроллера с другого контроллера

Образец снимка экрана прилагается. http://imgur.com/a/fuD5D

Мой вопрос: У меня есть BorderPane, который является своего рода корневого контейнера в моем случае (RootBorderPane.fmxl, RootBorderPaneController.java). Представление спроектировано с использованием построителя сцен. Я собираюсь использовать левую сторону в качестве панели навигации и на основе выбора с левой стороны, я загружу новое представление в центральной области RootBorderPane. У меня есть другие представления, подобные этим (View1.fxml, View2.fxml, View3.fxml и т. Д.) (С использованием сценария) и соответствующие контроллеры (View1Controller.java, View2Controller.java, View3Controller.java и т. Д.). View1, View2, View3 содержит TableViews самостоятельно. Теперь у меня есть несколько кнопок (Button1, Button2, Button3 и т. Д.) В левой части RootBorderPane, и если я нажму кнопку Button1, а затем я должен загрузить мой View1 (View1.fxml) и установить его в области центра RootBorderPane.

Я нажал кнопку «Button1», нажав кнопку мыши, я загрузил View1 и установил его в центре RootBorderPane. Эта логика находится внутри RootBorderPaneController.java View1 содержит TableView, и данные для табличного представления загружаются и устанавливаются на метод initializable() контроллера View1 (View1Controller.java) Я могу добиться всего сказанного выше.

Проблема: У меня есть кнопка «Добавить и удалить» на панели навигации, и эти кнопки должны быть включены/отключены на основе записи, выбранной в представлении View1. (Кнопка удаления должна быть активирована, если запись была выбрана в виде таблицы в противном случае. Кнопка «Добавить» должна быть включена, если в таблице не выбрана запись).

Непосредственно или косвенно мои поля вопросов для доступа к одному контроллеру с другого контроллера. Есть ли какой-нибудь элегантный подход к дизайну, чтобы сделать это вместо того, чтобы хранить 1 контрольную ссылку в другом контроллере.

Заранее спасибо

+0

См http://stackoverflow.com/questions/32342864/applying-mvc-with-javafx –

ответ

0

в одну сторону, чтобы получить доступ к контроллеру ваших subPanes (View_1 ... View_n) является, чтобы загрузить их, как вы делаете это для корневой панели.

// Load root layout from fxml file. 
FXMLLoader loader = new FXMLLoader(); 
rootLayout = loader.load(getClass().getResource("BorderPane.fxml").openStream()); 

BorderPaneController bpc = (BorderPaneController) loader.getController(); 

List<Pane> subPaneList = new ArrayList<>(); 
for (int i = 0; i < 30; i++) { 
    loader = new FXMLLoader(); 
    loader.setLocation(MainApp.class.getResource("View" + i + ".fxml")); 
    subPaneList.add((Pane) loader.load()); 
} 
bpc.setSubPaneList(subPaneList); 

// Show the scene containing the root layout. 
Scene scene = new Scene(rootLayout); 
primaryStage.setScene(scene); 
primaryStage.show(); 

теперь вы просто нужен метод setSubPaneList (..) в контроллере, и вы битами на канал будет иметь возможность доступа открытые методы (например, геттер/сеттер) ваших subPanes

+0

Вы не должны иметь цикл, просто номер кнопки, чтобы загрузить правый вид. – pdem

0

кажется, что вы загружаете динамически вид при помощи FXML погрузчика, так что здесь правило для его использования:

  1. не используйте статический метод FXMLLoader, intanciate в FXMLLoader иметь больше возможностей на нем (т.е. экземпляра узла контроллера &)
  2. Получите экземпляр дочернего контроллера, заданного FXMLLoader, с основного контроллера.
  3. выберите общий способ работы между родительскими контроллерами: я предлагаю метод selectedProperty().
  4. Получить эту недвижимость через интерфейс, так он доступен для всех дочерних контроллеров

Я использую свойство работать между контроллерами, в вашем случае selectedProperty из TableView должно быть идеальным решением: вы можете иметь выбранный экземпляр , и у вас есть событие выбора/выбора, которое можно использовать двумя способами: просто привяжите его или добавьте слушателя изменения, сделанного в tableView.
Для этого случая связывания достаточно.

В этом решении есть много файлов, так что вот главный трюк: от основного контроллера есть экземпляр выбранного свойства текущего дочернего элемента и привяжите его к visibleProperty вашей кнопки, чтобы показать его.

buttonOpen.disableProperty().bind(controller.selectedProperty().isNull()); 

Вам нужно, что selectedProperty снова в коде открытой кнопки

public void open(){ 
//TODO open in a view 
System.out.println("open the object"+selectedProperty().get() 
} 

Полные источники:

файлов Java

/** 
* App launch 
*/ 
public class SOFx extends Application{ 

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

    @Override 
    public void start(Stage primaryStage) throws Exception { 
    primaryStage.setTitle ("SO test"); 
    //static loading for index, don't need the controller. 
    Parent root = FXMLLoader.load(getClass().getResource("Index.fxml"),null); 
    Scene scene = new Scene(root); 
    primaryStage.setMaximized(true); 
    primaryStage.setScene(scene); 
    primaryStage.show(); 
    } 
} 

/** 
* Main Controller 
*/ 
public class IndexController { 


    @FXML 
    private BorderPane root; 

    @FXML 
    private Button buttonOpen; 

    private ObjectProperty<Object> selectedProperty; 

    public FXMLLoader loadFXML(URL url, ResourceBundle resources){ 
    FXMLLoader fxmlLoader = new FXMLLoader(); 
    fxmlLoader.setLocation (url); 
    fxmlLoader.setResources(resources); 
    try { 
     fxmlLoader.load(); 
     return fxmlLoader; 
    } catch (IOException e) { 
     e.printStackTrace(System.err); 
     throw new IllegalStateException(e); 
    } 
    } 

    public void button1(){ 
    FXMLLoader loadFXML = loadFXML(getClass().getResource("View1.fxml"),null); 
    root.setCenter(loadFXML.getRoot()); 
    ICenterController controller = (ICenterController) loadFXML.getController(); 
    selectedProperty = controller.selectedProperty(); 
    buttonOpen.disableProperty().bind(selectedProperty.isNull()); 
    } 

    public void open(){ 
    //TODO open in a view 
    System.out.println("open the object"+selectedProperty.get()); 
    } 

} 

/** 
* Interface of Center controllers 
*/ 
public interface ICenterController { 
ObjectProperty<Object> selectedProperty(); 
} 



/** 
* Child controller 
*/ 
public class View1Controller implements ICenterController { 

    private static final ObjectProperty<Object> selectedProperty = new SimpleObjectProperty(); 

    @Override 
    public ObjectProperty<Object> selectedProperty() { 
    return selectedProperty; 
    } 

    /** 
    * simulate TableView selection/deselection 
    */ 
    public void select(){ 
    selectedProperty.set(new Object()); 
    } 

    public void deselect(){ 
    selectedProperty.set(null); 
    } 

} 

FXML файлы, я не» t сделать полный TableView, я имитирую его кнопками

Index.fxml

<BorderPane xmlns="http://javafx.com/javafx/8.0.51" xmlns:fx="http://javafx.com/fxml/1" 
     fx:controller="pdem.stackoverflow.IndexController" fx:id="root"> 

     <left> 
      <VBox> 
       <Button onAction="#button1" text="view1"/> 
       <Button fx:id="buttonOpen" text="open"/> 
      </VBox> 

     </left> 


    </BorderPane> 

View1.fxml

<VBox xmlns="http://javafx.com/javafx/8.0.51" xmlns:fx="http://javafx.com/fxml/1" 
    fx:controller="pdem.stackoverflow.View1Controller" > 
      <Button onAction="#select" text="select"/> 
      <Button onAction="#deselect" text="deselect"/> 
</VBox> 
Смежные вопросы