我没有MCV代码示例,因为问题更加普遍,而且我认为特定代码实际上并没有太大的区别。
我有一个GUI应用程序,其中包含多个Elements(日期选择器,下拉列表,输入字段,tabletreeview),并且根据JavaFX,一个ControllerClass随着时间的推移变得很大。
因此,我正在寻找一种将其拆分的方法。在研究中,我发现了两种主要方法:
从UI部分中获取更多的程序逻辑,这当然总是有意义的,我在某些部分中做到了,但是对于许多部分来说似乎并不方便,例如,如果我有一个使用六个不同GUI元素的函数从控制器类中提取该方法似乎很奇怪,因为我需要在函数调用中为其提供所有这些GUI元素引用。有什么更好的Defaut我缺少的方式吗?就像仅使用setter / getter填充Controller类并为每个方法this
提供参数一样,使其可以使用this.dropbox1
?
我发现的第二种方法是将GUI本身分为几个场景。就像this的问题一样,但我不知道如何将一个GUI拆分为多个场景并仍然将其保存在一个窗口中。我确实意识到您可以在主FXML文件中加载其他FXML文件,但是我不确定如何在一个窗口中将它们组合到GUI中。如果有人为此提供了一些示例代码,我将不胜感激。
答案 0 :(得分:1)
欢迎来到Stackoverflow Labib,关于拆分事宜:
您可以拥有一个仅包含GridPane(或其他)的根FXML,但是我将继续使用GridPane作为前提,现在,如果您在该根FXML文件中设置了Grid(无内容),已经有一个完成的GUI,您应该对grid-cell需要多大有一个清晰的想法。在您的主要班级中,您有:
扩展应用程序并启动GUI的主类
$(document).ready(function() {
var i=1;
jQuery(".btn_remove").hide();
$('#more_btn').click(function() {
i++;
$clone = $('#first').clone(true);
$clone.attr('id', "row" + i);
$clone.find('.btn_remove').attr('data-remove-id', 'row'+i).show();
$('#myTable tbody').append($clone);
});
$('#myTable').on('click','.btn_remove',function(){
var button_id = $(this).data("remove-id");
alert(button_id)
$('#row'+button_id+'').remove();
});
});
现在您拥有public class GUI extends Application {
private Stage stage;
private GridPane rootGrid;
@Override
public void start(Stage stage) {
this.stage = stage;
// Load root layout from fxml file.
FXMLLoader loader = new FXMLLoader();
loader.setLocation(WindowRoot.class.getResource("RootGrid.fxml"));
rootGrid = (GridPane) loader.load();
// Show the scene containing the root layout.
Scene scene = new Scene(rootGrid);
stage.setTitle("Test");
stage.show();
//fill the Grid
setupGrid();
}
作为类属性,它只是rootGrid
中设置的具有空行/列的网格,可以很简单:
FXML示例,两行两列,没有内容
RootGrid.fxml
现在,您要为每个要填充的单元格创建FXML文档,在该FXML中,您将拥有一个包含该单元格内容的AnchorPane。然后,将其作为<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<GridPane xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.141">
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" />
<RowConstraints minHeight="10.0" prefHeight="30.0" />
</rowConstraints>
<columnConstraints>
<ColumnConstraints minWidth="10.0" prefWidth="100.0" />
<ColumnConstraints minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
</GridPane>
方法的一部分添加到网格中。假设您在一个简单的示例中想要一个菜单栏。为菜单创建FXML:
简单菜单fxml示例:
start
并将其作为<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.141">
<children>
<MenuBar>
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" text="Close" />
</items>
</Menu>
</menus>
</MenuBar>
</children>
</AnchorPane>
方法的一部分添加到网格中(但可能将其提取到您在开始时调用的方法中,例如start
:
设置网格,在开始(阶段)中调用
setupGrid()
您将需要try / except IO块,将它们省略以提高可读性。对于其他“ Root-Panes”,您将需要其他设置方法,例如,使用borderPane时,您将拥有private void setupGrid() {
// Add Menubar
FXMLLoader loader = new FXMLLoader();
loader.setLocation(WindowRoot.class.getResource("menubar.fxml"));
AnchorPane anchor = (AnchorPane) loader.load();
//put it in first column, first row
GridPane.setConstraints(anchor, 0, 0);
//optional, let it span both/all columns
GridPane.setRowSpan(anchor, 2);
rootGrid.getChildren().add(anchor);
之类的东西。
希望能帮助到你。玩得开心。
答案 1 :(得分:1)
如果使用FXML,最简单的事情是为FXML(一对一)设置一个控制器,而且我也添加了CSS,这是一种模式。
然后,您必须将屏幕分成几部分:2种方法:
然后,您必须在控制器之间进行通讯,最好是拥有一个模型层,并通过单例进行共享,例如使用afterburnerfx(一个很小的注射器)
使用fx:include时,还可以使用“嵌套控制器”从其父级获取子级控制器的引用。
最后一个对象可能是具有可观察性的javaFX Bean,并且您仅将可观察的而不是可视的组件从一个控制器公开给另一个控制器:这样,您的组件之间就会出现松散耦合。