需要你的帮助! 这可能更多的是设计视角,但我在我的应用程序中使用这种模式,所以想得到一个想法。
附加了示例屏幕截图。 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。 现在我在RootBorderPane的左边有几个按钮(Button1,Button2,Button3等),如果我点击Button1然后我应该加载我的View1(View1.fxml)并在RootBorderPane中心区域设置它。
我单击“Button1”,在按钮上单击我加载了View1并将其设置在RootBorderPane的中心。该逻辑位于RootBorderPaneController.java中 View1包含一个TableView,并且在View1的控制器(View1Controller.java)的initializable()方法上加载和设置表视图的数据 我能够完成上述所有说法。
问题: 我在导航面板上有添加和删除按钮,这些按钮应根据在View1的tableview上选择的记录启用/禁用。 (如果在桌面视图上选择了记录,则应启用删除按钮,否则如果在桌面视图中未选择任何记录,则应启用“添加”按钮。)
直接或间接地我的问题搁置到从另一个控制器访问一个控制器。有没有优雅的设计方法来做到这一点,而不是在另一个控制器中保留1个控制器的参考。
先谢谢
答案 0 :(得分:0)
允许您访问subPanes(View_1 ... View_n)控制器的一种方法是在为根窗格执行操作时加载它们。
String(contentsOf:encoding:)
现在你只需要在你的bpc控制器中使用setSubPaneList(..)方法,你就可以访问你的subPanes的公共方法(例如getter / setter)
答案 1 :(得分:0)
您似乎使用FXML Loader动态加载View,因此以下是使用它的规则:
我使用Property在控制器之间操作,在你的情况下,TableView的selectedProperty应该是理想的解决方案:你可以拥有所选的实例,并且你有选择/取消选择的事件,可以通过两种方式使用:just绑定它,或添加在tableView中完成的更改的监听器 对于这种情况,绑定就足够了。
该解决方案涉及许多文件,因此主要技巧如下:从主控制器获取当前子节点的selectedProperty实例,并将其绑定到按钮的visibleProperty,以显示它。 / p>
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文件,我没有做完全的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>