It seems that you load dynamically the View using FXML Loader, so here are the rule for using it:
- Don't use static method of FXMLLoader, intanciate the FXMLLoader to have more options on it (i.e. the controller & node instance)
- Get the instance of the child Controller given by the FXMLLoader, from the main Controller.
- choose a common way to operate between parent-child controllers: I propose a selectedProperty() method.
- Get this property from an interface so it is accessible for all child controllers
I use Property to operate between controllers, in your case the selectedProperty of TableView should be the ideal solution: you can have the selected instance, and you have the event of selection/deselection, that can be used in 2 ways: just bind it, or add a listener of the changement done in tableView.
For this case, the bind is enough.
There are many files involved in that solution, so here is the main trick: From the main controller, have the instance of the selectedProperty of the current child, and bind it to the visibleProperty of your button, to show it.
buttonOpen.disableProperty().bind(controller.selectedProperty().isNull());
You will need that selectedProperty again to in the code of the open button
public void open(){
//TODO open in a view
System.out.println("open the object"+selectedProperty().get()
}
Full sources:
Java files
/**
* 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 files, I don't do a full TableView, I simulate it with buttons
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>