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();
}
});
}
}
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