JavaFx从单个FXML生成多个场景

时间:2016-04-08 17:26:11

标签: java javafx

我启动了一个与数据库交互的javafx项目(添加新的,编辑,删除,查找......)。 我的数据库包含很多表,每个表都需要自己的场景(几乎相同!!!) 所以我的问题是:不是实现~20 fxml文件,是否可以制作一个fxml文件,根据传递给控制器​​的类名称(例如)改变其内容?
如果是的话,任何提示来实现它? 这是我尝试过的:
为每个TableClass添加了一个HashMap,其中包含场景中所需的所有属性,并在ControllerClass中迭代它以将控件添加到场景中!但失败!
TableSampleClass:

public class TableSampleClass{
public static final HashMap<String, String> attr;
static {
    attr = new HashMap<String, String>();
    attr.put("ref", "text");
    attr.put("name", "text");
    attr.put("adress", "text");
    attr.put("Mobile", "tel");
    attr.put("mail", "mail");
    attr.put("isalive", "checkbox");//just to illustrate what i want !
    }
     ........
   }

ControllerClass:

@FXML
private AnchorPane pane;
@Override
public void initialize(URL location, ResourceBundle resources)
{     Iterator it = TableSampleClass.attr.entrySet().iterator();
    while(it.hasNext())
    {
        Map.Entry pair = (Map.Entry)it.next();
        switch (pair.getValue().toString()){
        case "text":
            TextField txt =new TextField(pair.getValue().toString());
            txt.setPromptText(pair.getKey().toString());
            Label lbl =new Label(pair.getKey().toString());
            pane.getChildren().add(txt);
            break;
        }
    }
}

我希望我能清楚地解释自己!!

2 个答案:

答案 0 :(得分:0)

使用Custom component FXML pattern。这种方式的工作方式是编写一个控制器类,在构造函数中加载相应的FXML文件。由于您通过调用构造函数来使用它,因此您可以允许构造函数获取参数并在加载FXML后使用这些参数来配置组件。

你展示的代码对我来说并不是很清楚,但这个结构看起来像是:

public class MyCustomTableDisplay extends AnchorPane {

    @FXML
    private AnchorPane pane ;

    public MyCustomTableDisplay(Map<String, String> config) {
        try {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("path/to/fxml"));
            loader.setRoot(this); 
            loader.setController(this);
            loader.load();
        } catch (IOException exc) {
            throw new RuntimeException(exc);
        }

        // now configure pane based on config passed in...
    }
}

FXML文件必须使用“动态根”,这意味着通过调用setRoot(...)上的FXMLLoader来确定根元素(如上面的代码所示)。所以它看起来像

<!-- imports omitted -->
<fx:root type="AnchorPane" xmlns:fx="..." ... >
    <!-- usual fxml stuff -->
    <AnchorPane fx:id="pane" ...>

    <AnchorPane>
</fx:root>

现在你做了

Map<String, String> config = new HashMap<>();
// populate config...
MyCustomTableDisplay display = new MyCustomTableDisplay(config);
Scene scene = new Scene(display);
// etc...

type的{​​{1}}基本上可以是任何节点类型,但必须与类的类型匹配。然后,您可以包含所需的任何fxml内容。该类充当控制器,因此您可以通常的方式从FXML注入值:当在加载器上调用fx:root方法时,它们将被初始化(像往常一样)。

答案 1 :(得分:0)

潜在方法

有一些第三方库可动态生成JavaFX的表单和界面UI,例如FXForm2ControlsFX PropertySheets

也可以生成一个table from data dynamically,看起来它可能就像你实际上要做的那样。

关于FXML

对于大多数系统,您不使用FXML定义窗口小部件的内部GUI。而是通过内省数据或Java类动态生成低级字段。您要做的就是将相应的库添加到SceneBuilder并导入高级控件(例如ControlsFX PropertySheet),只是在FXML中声明它而不是在FXML中定义控件的详细字段。

如果需要,并且链接库中的系统不是您所需要的,您还可以创建自定义控件和import those for use in SceneBuilder,尽管这些仍然可以以类似方式动态生成详细信息字段通过reflection进行数据或Java类内省。

通过内省生成动态字段

基于反射创建自定义控件是仅为经验丰富的Java和JavaFX开发人员推荐的高级主题。您可以通过PropertySheet implementation实用程序类查看java beans这种方法的示例代码,该代码使用IntrospectorBeanPropertyUtils。 Java bean是一个非常大的主题,我在这里不能详细介绍。只需要java bean规范的某些功能即可实现所需,因为规范的其他部分已被新的JavaFX功能(如属性和绑定)废弃。