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)
就实际将注释放入布局而言,您可以执行以下操作:
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)
希望这可以帮助!
| 归档时间: |
|
| 查看次数: |
1728 次 |
| 最近记录: |