从动态模型生成视图

时间:2013-03-19 18:45:22

标签: java swing oop model-view-controller polymorphism

我有一个可以在运行时修改的模型。这是一个例子:

public class JavaMethod
{
   private String            name;
   private List<Parameter>   parameters;
   private boolean           isConstructor; // this is an example
}

参数可以有不同的类型(integerbooleanstringfloat ...)和不同的有效值。例如,名为 age 的整数参数只能保存正整数。

问题是我想用Swing生成一个视图来配置JavaMethod对象,但我不确定这样做的正确方法。

例如, age 参数是一个正整数,它将链接到一个扩展JTextField的类,以防止输入任何字母为负数。另一个名为 numberOfFingers 的整数参数,范围从8到12,将链接到扩展JComboBox的类,允许选择该范围内的选项。

我可以通过向Parameter对象生成适当的Swing组件的任务来实现多态性,但是我的模型将知道视图是如何生成的。

为这样的模型生成视图的正确方法是什么? 我所能想到的(没有参与视图生成的模型)是控制器中的一种巨型开关,通过读取参数的详细信息来选择好的组件。

由于

2 个答案:

答案 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