[英]Generate form elements based on type, with overrides
With a few applications I'm building, I could use the ability to generate dynamic forms for filling in arbitrary lists of variables. 通过构建一些应用程序,我可以使用生成动态表单的功能来填写任意变量列表。 For example, when running a Lua script that reads in an arbitrary file format, the script may need unique information to decode that format (eg separating character for a CSV). 例如,当运行以任意文件格式读取的Lua脚本时,该脚本可能需要唯一的信息来解码该格式(例如,分隔CSV字符)。 Essentially, I want something similar to Unity 's inspector. 本质上,我想要类似于Unity的检查器的东西。
I have a HashMap
that maps a Class
to a Handler
: 我有一个将Class
映射到Handler
的HashMap
:
private interface Handler {
Control handle(GridPane grid, Integer row);
}
private static final HashMap<Class, Handler> FormInputs =
new HashMap<Class, Handler>() {
{
// String
put(String.class, (grid, row) -> CreateStringInput(grid, row));
// Integer
put(int.class, (grid, row) -> CreateIntegerInput(grid, row));
put(Integer.class, (grid, row) -> CreateIntegerInput(grid, row));
// Float
put(float.class, (grid, row) -> CreateFloatInput(grid, row));
// Directory
put(Path.class, (grid, row) -> CreateFileInput(grid, row));
put(File.class, (grid, row) -> CreateFileInput(grid, row));
}
};
When the form is created, it uses getFields()
to get the list of fields from the passed Class
, and when the form is constructed, it creates a simple GridPane
and fills it with labels and controls. 创建表单时,它使用getFields()
从传递的Class
获取字段列表,构造表单时,它创建一个简单的GridPane
并用标签和控件填充它。
In theory, this should work fine, but I noticed with the Path
class that the class does not always line up with its intended use. 从理论上讲,这应该可以正常工作,但是我在Path
类中注意到该类并不总是与其预期用途保持一致。 A Path
may point to a file or a directory, which require different settings for the browsing dialog. Path
可能指向文件或目录,这需要对浏览对话框进行不同的设置。 Similarly, a String
may be used for any number of things, and may need certain validation. 类似地, String
可以用于许多事物,并且可能需要某些验证。
What would be the most friendly approach for overriding the type check and explicitly stating which form input to use? 覆盖类型检查并明确说明要使用哪种表单输入的最友好方法是什么? I looked into using Decorators, but those seem to be for extending existing functions of the decorated object, whereas I want to imbue them with extra information. 我考虑使用Decorator,但这些装饰似乎是为了扩展装饰对象的现有功能,而我想向它们灌输额外的信息。
edit: For further context, I would like to be able to do things like Unity's [Range()] decorator, whereby numeric classes become represented by a slider between the min and max values. 编辑:对于进一步的上下文,我希望能够做类似Unity的[Range()]装饰器之类的事情,从而使数值类由最小值和最大值之间的滑块表示。
edit 2: To clarify and simplify: The Form
class generates an automatic form based on a class. 编辑2:澄清和简化: Form
类基于一个类生成一个自动表单。 For example, passing it the following class 例如,将其传递给以下类
public class TestClass {
public boolean bool1;
public Boolean bool2;
public String string1;
public String string2;
public Integer int1;
public int int2;
public Path path1;
public File file1;
}
results in the following form: 结果为以下形式:
I want to be able to indicate, in the class, which fields should be handled differently. 我希望能够在课堂上指出哪些字段应以不同的方式处理。 Ideally I also want this to work by passing in an array of mixed variables, and I want to be able to define a custom schema, like can be done with Unity and custom inspectors. 理想情况下,我还希望通过传递混合变量数组来实现此目的,并且希望能够定义自定义模式,就像使用Unity和自定义检查器可以完成的那样。
The best method I have come up with involves a bit of rearranging. 我想出的最好方法涉及一些重新排列。 It only works automatically for custom classes, but it allows for some customisation after initialisation. 它仅对自定义类自动起作用,但允许在初始化后进行一些自定义。
First, write a public interface for custom classes to implement that allows them to define a custom list of controls: 首先,为自定义类编写一个公共接口以实现,以允许它们定义自定义控件列表:
public interface FormLayout {
List<Input> getLayout();
}
Then, in the constructor, instead of initialising a list of fields, check if the object defines its own layout: 然后,在构造函数中,而不是初始化字段列表,而是检查对象是否定义了自己的布局:
public Form (Object objRef) {
Field[] fields = objRef.getClass().getFields();
if(objRef instanceof Form.FormLayout) {
inputs = ((FormLayout) objRef).getLayout();
}
else {
inputs = new ArrayList<>();
for (int i = 0; i < fields.length; i++) {
inputs.add(new Input(fields[i].getName(), FormInputs.get(fields[i].getType())));
}
}
}
Now you have a list of defined inputs that can be manipulated before constructing the form, and the ability to define a custom layout for a class. 现在,您有了定义的输入列表,可以在构造表单之前对其进行操作,并且可以为类定义自定义布局。
Further work will need to be done to handle associating an input with a field so the user input actually makes its way to the right variable, but this seems to be the most reasonable approach. 需要做进一步的工作来处理将输入与字段相关联的操作,以便用户输入实际上可以到达正确的变量,但这似乎是最合理的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.