根据属性创建swing组件

And*_*ter 5 java swing annotations

我有一个小程序,它能够在运行时加载组件.我想为这些组件编写一个小API.主程序应该识别组件中的属性,并为每个属性创建一个swing组件.我的想法是使用注释,例如:

@Property(name = "X",  PropertyType.Textfield, description = "Value for X")
private int x;
Run Code Online (Sandbox Code Playgroud)

你怎么看待这件事?有什么问题吗?是否有类似的实施或其他选择?感谢您的所有建议和提示!

更新 请注意,我无法使用第三方库.

更新 我想创建一个抽象类,它能够根据Conceet类的属性创建swing组件.抽象类控制演示文稿.例如(伪代码):

public class A {
    /**
     * Create swing component based on the concret class
     * In this example class A should create a jTextField with a jLable "Cities". So I have not to create each component manuel, 
     * If the text field changed the attribute for cities should set (My idea was with propertyChangesSupport).
     */
}

public class B extends A {
    @Property(name = "Cities",  PropertyType.Textfield, description = "Number of cities")
    private int cities;
}
Run Code Online (Sandbox Code Playgroud)

tob*_*bii 3

就实际将注释放入布局而言,您可以执行以下操作:

public class A extends JPanel {

A() {
    this.setLayout(new FlowLayout());
    addProperties();
}

private void addProperties() {
    for (Field field : this.getClass().getDeclaredFields()) {
        Property prop = field.getAnnotation(Property.class);
        if (prop != null) {
            createAndAddComponents(prop);
        }
    }
}

private void createAndAddComponents(Property prop) {
    JLabel jLabel = new JLabel(prop.name());
    this.add(jLabel);
    switch (prop.type()) {
    case Textfield:
        JTextField jTextField = new JTextField();
        this.add(jTextField);
    case ...
        ...
    }
}
}
Run Code Online (Sandbox Code Playgroud)

当然,这看起来不会很花哨,因为我用它FlowLayout来避免示例中的混乱。对于 的值JTextField,我不确定你想采取什么方向。您可以添加DocumentListener将直接更新相关对象或其他内容的 s Field,但我不确定要求是什么。这是一个想法:

jTextField.getDocument().addDocumentListener(new DocumentListener() {

@Override
public void insertUpdate(DocumentEvent e) {
    try {
        int value = Integer.parseInt(jTextField.getText());
        field.setInt(A.this, value);
    } catch (NumberFormatException e1) {
    } catch (IllegalArgumentException e1) {
    } catch (IllegalAccessException e1) {
    }
}

......
});
Run Code Online (Sandbox Code Playgroud)

当您设置值时,您还可以在其中执行一些 PropertyChangeSupport 操作。

我使用 GroupLayout 和 PropertyChangeSupport 制作了一个可运行的示例,实际上看起来还不错...... 运行示例

代码有点混乱(特别是我对 GroupLayout 的使用,抱歉),但这里是为了以防万一您需要看一些东西..我希望我没有让这变得太混乱...

public class B extends A {
    @Property(name = "Cities",  type = PropertyType.Textfield, description = "Number of cities")
    private int cities;
    @Property(name = "Cool Cities",  type = PropertyType.Textfield, description = "Number of cool cities")
    private int coolCities;

    public static void main(String[] args) {
        final B b = new B();
        b.addPropertyChangeListener("cities", new PropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                System.out.println("Cities: " + b.cities);
            }

        });
        b.addPropertyChangeListener("coolCities", new PropertyChangeListener() {

            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                System.out.println("Cool Cities: " + b.coolCities);
            }

        });

        JFrame frame = new JFrame();
        frame.add(b);
        frame.setVisible(true);
    }
}


public class A extends JPanel {

    //Need this retention policy, otherwise the annotations aren't available at runtime:
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Property {
        String name();
        PropertyType type();
        String description();
    }

    public enum PropertyType {
        Textfield
    }


    A() {
        addProperties();
    }

    private void addProperties() {
        GroupLayout layout = new GroupLayout(this);
        this.setLayout(layout);
        layout.setAutoCreateContainerGaps(true);
        layout.setAutoCreateGaps(true);
        Group column1 = layout.createParallelGroup();
        Group column2 = layout.createParallelGroup();
        Group vertical = layout.createSequentialGroup();

        for (Field field : this.getClass().getDeclaredFields()) {
            field.setAccessible(true); // only needed for setting the value.
            Property prop = field.getAnnotation(Property.class);
            if (prop != null) {
                Group row = layout.createParallelGroup();

                createAndAddComponents( prop, column1, column2, row, field );
                vertical.addGroup(row);
            }
        }
        Group horizontal = layout.createSequentialGroup();
        horizontal.addGroup(column1);
        horizontal.addGroup(column2);
        layout.setHorizontalGroup(horizontal);
        layout.setVerticalGroup(vertical);
    }

    private void createAndAddComponents(Property prop, Group column1, Group column2, Group vertical, final Field field) {
        JLabel jLabel = new JLabel(prop.name() + " (" + prop.description() + ")");
        column1.addComponent(jLabel);
        vertical.addComponent(jLabel);
        switch (prop.type()) {
        case Textfield:
            final JTextField jTextField = new JTextField();
            jTextField.getDocument().addDocumentListener(new DocumentListener() {

                @Override
                public void insertUpdate(DocumentEvent e) {
                    updateValue();
                }

                @Override
                public void changedUpdate(DocumentEvent e) {
                    updateValue();
                }

                @Override
                public void removeUpdate(DocumentEvent e) {
                    updateValue();
                }

                private void updateValue() {
                    try {
                        int value = Integer.parseInt(jTextField.getText());
                        field.setInt(A.this, value);
                        firePropertyChange(field.getName(), "figure out old", value);
                    } catch (NumberFormatException e1) {
                    } catch (IllegalArgumentException e1) {
                    } catch (IllegalAccessException e1) {
                    }
                }

            });
            column2.addComponent(jTextField);
            vertical.addComponent(jTextField, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE, GroupLayout.PREFERRED_SIZE);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助!