2017-06-17 1 views
0

J'essaye de faire une liaison de données unidirectionnelle dans java pour les objets swing, juste comme un exercice. Actuellement, pour les objets swing qui étendent JTextComponent, j'ajoute un écouteur de document qui met également à jour le stockage des données de sauvegarde.Field.set throws IllegalArgumentException

public class Binder { 

Map<JComponent, Map.Entry<WeakReference, Field>> map = new WeakHashMap<>(); 
AutoDocumentListener adl; 

public Binder() { 
    adl = new AutoDocumentListener(); 
} 

public void bind(Object instance, String varName, JComponent element, String property) { 
    Field field; 
    try { 
     field = instance.getClass().getDeclaredField(varName); 
     field.setAccessible(true); 
     map.put(element, 
       new AbstractMap.SimpleEntry<WeakReference, Field>(new WeakReference(instance), field)); 

     if (element instanceof JTextComponent) { 
      element = (JTextComponent) element; 
      Document eldoc = ((JTextComponent) element).getDocument(); 
      eldoc.putProperty("origin", element); 

      eldoc.addDocumentListener(adl); 
     } else { } 
    } catch (NoSuchFieldException | SecurityException ex) { 
     Logger.getLogger(Binder.class.getName()).log(Level.SEVERE, null, ex); 
    } 
} 

class AutoDocumentListener implements DocumentListener { 

    @Override 
    public void insertUpdate(DocumentEvent evt) { 
     JTextComponent jc = (JTextComponent) evt.getDocument().getProperty("origin"); 
     Map.Entry<WeakReference, Field> dataToUpdate = map.get(jc); 
     if (dataToUpdate != null) { 
      try { 
       Object data = jc.getText(); 
       dataToUpdate.getValue().set(dataToUpdate.getKey(), data); 
      } catch (IllegalArgumentException | IllegalAccessException ex) { 
       Logger.getLogger(Binder.class.getName()).log(Level.SEVERE, null, ex); 
      } 
     } 
    } 
    @Override 
    public void removeUpdate(DocumentEvent evt) { 
    } 
    @Override 
    public void changedUpdate(DocumentEvent e) { 
    } 
    } 
} 

Le problème est, à la ligne suivante je reçois un IllegalArgumentException:

dataToUpdate.getValue().set(dataToUpdate.getKey(), data); 

java.lang.IllegalArgumentException: Can not set java.lang.String field org.jbind.test.TestClass.data to java.lang.ref.WeakReference 

Pour autant que je peux voir dans la documentation, l'appel à Field.set est correcte. Donc, je ne comprends pas ce qui ne va pas.

J'appelle la fonction avec le code suivant:

public class TestClass { 
public String data = "Text1"; 

public void init() { 
    Binder binder = new Binder(); 

    JTextField jtf = new JTextField(data); 
    binder.bind(this, "data", jtf, ""); 
    jtf.setText("Text2"); 
    System.out.println(data); 
} 

public static void main(String[] args) { 
    SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      new TestClass().init(); 
     } 
    }); 

    } 
} 

Répondre

1

Je pense que vous avez besoin pour obtenir la valeur de la clé

dataToUpdate.getValue().set(dataToUpdate.getKey().get(), data); 

dataToUpdate.getKey() retourne un WeakReference Vous essayez de définir le champ "data" sur une instance de WeakReference. Vous souhaitez définir le champ "data" sur une instance de TestClass.

+0

vous avez raison. Je ne sais pas pourquoi j'ai supposé que l'affectation peut être faite à travers le WeakRef. Je ne l'ai pas vu hériter d'un get(). Merci. – DebD