我有一个可以在运行时修改的模型。这是一个例子:
public class JavaMethod
{
private String name;
private List<Parameter> parameters;
private boolean isConstructor; // this is an example
}
参数可以有不同的类型(integer
,boolean
,string
,float
...)和不同的有效值。例如,名为 age 的整数参数只能保存正整数。
问题是我想用Swing生成一个视图来配置JavaMethod
对象,但我不确定这样做的正确方法。
例如, age 参数是一个正整数,它将链接到一个扩展JTextField
的类,以防止输入任何字母为负数。另一个名为 numberOfFingers 的整数参数,范围从8到12,将链接到扩展JComboBox
的类,允许选择该范围内的选项。
我可以通过向Parameter对象生成适当的Swing组件的任务来实现多态性,但是我的模型将知道视图是如何生成的。
为这样的模型生成视图的正确方法是什么? 我所能想到的(没有参与视图生成的模型)是控制器中的一种巨型开关,通过读取参数的详细信息来选择好的组件。
由于
答案 0 :(得分:1)
为此,您需要创建自定义PlainDocument
。例如,对于仅包含年龄值的JTextField
,您应该创建AgeDocument
类,如下所示:
import javax.swing.text.Document;
import javax.swing.text.PlainDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
class AgeDocument extends PlainDocument
{
@Override
public void insertString(int offs, String str, AttributeSet a) throws BadLocationException
{
/**Write your logic here**/
if (str == null)
{
return;
}
char[] arr = str.toCharArray();
for (int i = 0; i < arr.length; i++)
{
if (!Character.isDigit(arr[i]))//Checking for Non Numeric.
{
return;
}
if (Character.getNumericValue(arr[i])==0 )
{
try
{
int val = Integer.parseInt(getText(0,offs));
if (val == 0)
{
super.insertString(offs,"", a);//Don't allow to put 0 as age.
return;
}
}
catch (Exception ex){return;}
}
}
super.insertString(offs, new String(str), a);
}
}
每当您想将此AgeDocument
属性设置为JTextField
对象时,您只需编写JTextFieldOBject.setDocument(new AgeDocument ())
同样,您可以独立创建许多模型。并且可以在代码中的任何位置使用它们。
答案 1 :(得分:0)
解决此问题的最佳方法是使用访客模式。
例如:
import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.WindowConstants;
public class Main
{
public static class JavaMethod implements Iterable<Parameter>
{
private List<Parameter> parameters;
public JavaMethod()
{
this.parameters = new ArrayList<>();
// This is an example
this.parameters.add(new IntegerParameter());
this.parameters.add(new StringParameter());
}
@Override
public Iterator<Parameter> iterator()
{
return this.parameters.iterator();
}
}
public static interface Parameter
{
public void accept(ParameterVisitor visitor);
}
public static class IntegerParameter implements Parameter
{
public int value = 10;
@Override
public void accept(final ParameterVisitor visitor)
{
visitor.visit(this);
}
}
public static class StringParameter implements Parameter
{
public String value = "Hello";
@Override
public void accept(final ParameterVisitor visitor)
{
visitor.visit(this);
}
}
public static interface ParameterVisitor
{
void visit(StringParameter stringParameter);
void visit(IntegerParameter integerParameter);
}
public static class ParameterSwingVisitor implements ParameterVisitor
{
private final JComponent container;
public ParameterSwingVisitor(final JComponent container)
{
this.container = container;
}
@Override
public void visit(final StringParameter stringParameter)
{
this.container.add(new JTextField(stringParameter.value));
}
@Override
public void visit(final IntegerParameter integerParameter)
{
// This could be a custom component to pick numbers
this.container.add(new JLabel(String
.valueOf(integerParameter.value)));
}
}
public static void main(final String[] args)
{
EventQueue.invokeLater(new Runnable()
{
@Override
public void run()
{
JPanel myPanel = new JPanel(); // view
JavaMethod myMethod = new JavaMethod(); // model
final ParameterVisitor visitor = new ParameterSwingVisitor(
myPanel);
for (final Parameter picked : myMethod)
{
picked.accept(visitor); // This will add the appropriate
// swing
// component
}
JFrame myFrame = new JFrame("Visitor pattern");
myFrame.setContentPane(myPanel);
myFrame.setVisible(true);
myFrame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
myFrame.setSize(500, 500);
}
});
}
}
有关此模式的更多信息here。