Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>In my opinion (I know I shouldn't write opinions but only facts on stackoverflow answers, but here the question is "what do you think about it?"... :-) ) in this solution you are mixing Model and View information in class B (particularly having that PropertyType.Textfield in your annotation). I know MVC pattern is not a law (even Android Adapter breaks MVC contract and it's ok anyway :-) ), but it is generally considered good practice.</p> <p>If I'm getting you right you have class A that provides the view (swing components) for class B. So A is a view and B is a model. For this reason I wouldn't have B to extend A because it breaks the "IS A" relationship (B extends A means "B is a A" and in your case this would mean B is a view while it is not).</p> <p>As a different option, did you consider investigating an approach based on JavaBeans and PropertyEditors? it should be more in line with the regular management of "runtime-loaded" components in swing. See <a href="http://docs.oracle.com/javase/tutorial/javabeans/advanced/customization.html" rel="nofollow">http://docs.oracle.com/javase/tutorial/javabeans/advanced/customization.html</a></p> <p>I wrote a simple example just to show you what I mean:</p> <p>Here is my class B:</p> <pre><code>import java.awt.Color; public class B { private int x = 0; private Color c = Color.BLUE; private Address address; public B() { address = new Address(); address.setCity("Liverpool"); address.setState("England"); address.setStreet("Penny Lane"); address.setNumber("1"); address.setZip("12345"); } public int getX() { return x; } public void setX(int x) { this.x = x; } public Color getC() { return c; } public void setC(Color c) { this.c = c; } public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; } } </code></pre> <p>And this is my test GUI:</p> <pre><code>import java.awt.GridLayout; import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JTextField; public class Test extends JFrame { /** * */ private static final long serialVersionUID = 1L; public Test(Object b) { super("Test"); initGUI(b); } private void initGUI(Object b) { Class&lt;?&gt; c = b.getClass(); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLayout(new GridLayout(0, 2)); try { BeanInfo info = Introspector.getBeanInfo(c); for (PropertyDescriptor pd : info.getPropertyDescriptors()) { try { Method readMethod = pd.getReadMethod(); Object val = readMethod.invoke(b, new Object[0]); // Or you may want to access the field directly... but it has to be not-private // Field f = c.getDeclaredField(pd.getName()); // Object val = f.get(b); // // You can use annotations to filter... for instance just consider annotated // fields/methods and discard the others... // if (f.isAnnotationPresent(Property.class)) { // ... java.beans.PropertyEditor editor = java.beans.PropertyEditorManager.findEditor(val.getClass()); if (editor != null) { editor.setValue(val); add(new JLabel(pd.getDisplayName())); if (editor.supportsCustomEditor()) { add(editor.getCustomEditor()); } else { String[] tags = editor.getTags(); if (tags != null) { add(new JComboBox&lt;String&gt;(tags)); } else { if (editor.getAsText() != null) { add(new JTextField(editor.getAsText())); }else{ add(new JPanel()); } } } } } catch (SecurityException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } catch (IntrospectionException ex) { ex.printStackTrace(); } } public static void main(String[] args) { B b = new B(); Test t = new Test(b); t.pack(); t.setVisible(true); } } </code></pre> <p>PropertyEditorManager provides a default editor for int and for Color. What about my class Address?</p> <pre><code>public class Address { private String city; private String state; private String zip; private String street; private String number; public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getState() { return state; } public void setState(String state) { this.state = state; } public String getZip() { return zip; } public void setZip(String zip) { this.zip = zip; } public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } } </code></pre> <p>I provide a custom editor for class Address (PropertyEditorManager uses different strategies to discover class editors... I used naming convention) This is my AddressEditor class:</p> <pre><code>import java.awt.Component; import java.awt.FlowLayout; import java.beans.PropertyEditorSupport; import javax.swing.JPanel; import javax.swing.JTextField; public class AddressEditor extends PropertyEditorSupport { @Override public boolean supportsCustomEditor() { return true; } @Override public Component getCustomEditor() { Address value = (Address) getValue(); JPanel panel = new JPanel(); panel.setLayout(new FlowLayout()); panel.add(new JTextField(value.getStreet())); panel.add(new JTextField(value.getNumber())); panel.add(new JTextField(value.getCity())); panel.add(new JTextField(value.getState())); panel.add(new JTextField(value.getZip())); return panel; } } </code></pre> <p>This way B (and also Address) are just models and editors are provided to customize the views.</p> <p>Well... this was just to respond to your question about other options... I hope I didn't go too much out of track... :-)</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload