Newsgroup: it.comp.java
Titolo: Beans Bindings, piccolo chiarimento

Ciao a tutti
In questi giorni stavo cercando un modo "più pulito" per sincronizzare
i dati tra i componenti di un programma che devo consegnare a breve.
Per il momento utilizzo dei giri abbastanza orrendi e soprattutto
ingestibili dal punto di vista della manutenzione e del mantenimento
del codice, il 90% circa dei componenti che ho creato tira dentro di
se tramite costruttore tutti gli oggetti a cui vanno propagate le
modifiche.
Inoltre per come è adesso il codice, se tra un pò di tempo io o
qualcun altro dovesse metterci mano credo che mi sentirei fischiare le
orecchie del via degli accidenti che mi tirerebbero.
Cercando una soluzione ho notato che potevano aiutarmi i beans
bindings. Ho preso il mio buon netbeans 6.1 e mi sono messo a lavorare
su di una copia del progetto (così posso fare tutte le prove che
voglio senza combinare danni :D ).
fatto stà che il binding di netbeans mi lascia a piedi.. cioè io
partendo da un jTextFiled faccio il binding con la procedura guidata
linkando come taget il text e come source un oggetto Date presente
all'interno di un mio bean.artigianale.
La data sono sicuro che viene modificata, ho controllato facendo
stampare i valori delle variabili prima e dopo i vari assegnamenti e
gli indirizzi di memoria sono identici.
nel caso in cui verreste controllare il codice della classe che
contiene e genera la data lo riporto di seguito (lo so come codice fa
un pò pietà ma il generatore delle GUI di netbeans è troppo comodo...)
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.swing.JFormattedTextField;
/**
 *
 * @author  marco
 */
public class PnlInsertData extends javax.swing.JPanel {
    private Date data;
    public PnlInsertData() {
        initComponents();
        ftxtGg.addPropertyChangeListener(new
FtxtDataProperty(ftxtGg));
        ftxtMm.addPropertyChangeListener(new
FtxtDataProperty(ftxtMm));
        ftxtAa.addPropertyChangeListener(new
FtxtDataProperty(ftxtAa));
    }
    public Date getData() {
        return data;
    }
    public void setData(Date data) {
        this.data = data;
    }
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated
Code">
    private void initComponents() {
        ftxtGg = new javax.swing.JFormattedTextField();
        jLabel1 = new javax.swing.JLabel();
        ftxtMm = new javax.swing.JFormattedTextField();
        jLabel2 = new javax.swing.JLabel();
        ftxtAa = new javax.swing.JFormattedTextField();
        setBorder(javax.swing.BorderFactory.createTitledBorder(""));
        setAlignmentX(0.0F);
        setAlignmentY(0.0F);
        setMaximumSize(new java.awt.Dimension(32767, 55));
        setMinimumSize(new java.awt.Dimension(150, 55));
        setPreferredSize(new java.awt.Dimension(200, 55));
        ftxtGg.setFormatterFactory(new
javax.swing.text.DefaultFormatterFactory(new
javax.swing.text.NumberFormatter(new java.text.DecimalFormat("#0"))));
        ftxtGg.setAlignmentX(0.0F);
        ftxtGg.setAlignmentY(0.0F);
        ftxtGg.setMaximumSize(new java.awt.Dimension(50, 25));
        ftxtGg.setMinimumSize(new java.awt.Dimension(50, 25));
        ftxtGg.setPreferredSize(new java.awt.Dimension(50, 25));
        add(ftxtGg);
        jLabel1.setText("/");
        jLabel1.setAlignmentY(0.0F);
        jLabel1.setMaximumSize(new java.awt.Dimension(10, 25));
        jLabel1.setMinimumSize(new java.awt.Dimension(10, 25));
        jLabel1.setPreferredSize(new java.awt.Dimension(10, 25));
        add(jLabel1);
        ftxtMm.setFormatterFactory(new
javax.swing.text.DefaultFormatterFactory(new
javax.swing.text.NumberFormatter(new java.text.DecimalFormat("#0"))));
        ftxtMm.setAlignmentX(0.0F);
        ftxtMm.setAlignmentY(0.0F);
        ftxtMm.setMaximumSize(new java.awt.Dimension(50, 25));
        ftxtMm.setMinimumSize(new java.awt.Dimension(50, 25));
        ftxtMm.setPreferredSize(new java.awt.Dimension(50, 25));
        add(ftxtMm);
        jLabel2.setText("/");
        jLabel2.setAlignmentY(0.0F);
        jLabel2.setMaximumSize(new java.awt.Dimension(10, 25));
        jLabel2.setMinimumSize(new java.awt.Dimension(10, 25));
        jLabel2.setPreferredSize(new java.awt.Dimension(10, 25));
        add(jLabel2);
        ftxtAa.setFormatterFactory(new
javax.swing.text.DefaultFormatterFactory(new
javax.swing.text.NumberFormatter(new java.text.DecimalFormat("#0"))));
        ftxtAa.setAlignmentX(0.0F);
        ftxtAa.setAlignmentY(0.0F);
        ftxtAa.setMaximumSize(new java.awt.Dimension(50, 25));
        ftxtAa.setMinimumSize(new java.awt.Dimension(50, 25));
        ftxtAa.setPreferredSize(new java.awt.Dimension(50, 25));
        add(ftxtAa);
    }// </editor-fold>
    // Variables declaration - do not modify
    private javax.swing.JFormattedTextField ftxtAa;
    private javax.swing.JFormattedTextField ftxtGg;
    private javax.swing.JFormattedTextField ftxtMm;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    // End of variables declaration
    private class FtxtDataProperty implements PropertyChangeListener {
        private JFormattedTextField source;
        public FtxtDataProperty(JFormattedTextField source) {
            this.source = source;
        }
        public synchronized void propertyChange(PropertyChangeEvent
evt) {
            //if (source == evt.getSource()) {
                System.out.println(this.getClass().getName());
                // controllo dei dati
                String d = ftxtGg.getValue() + "/" +
(ftxtMm.getValue()) + "/" + (ftxtAa.getValue());
                System.out.println(d);
                SimpleDateFormat format = new SimpleDateFormat("dd/MM/
yyyy");
                try {
                    setData(format.parse(d));
                } catch (ParseException e) {
                    System.out.println("Impossibile parsare la data");
                }
                System.out.println(data);
            //}
        }
    }
}
Per quanto riguarda l'altro oggetto con cui vorrei collegare in
binding la data ad nu boolean non è altro che un JPanel con inserito
dentro il componente e l'oggetto a cui vorrei collegarmi in binding.
import org.jdesktop.beansbinding.AutoBinding;
import org.jdesktop.beansbinding.BeanProperty;
import org.jdesktop.beansbinding.Binding;
import org.jdesktop.beansbinding.Bindings;
import org.jdesktop.beansbinding.Converter;
import org.jdesktop.beansbinding.ELProperty;
/**
 *
 * @author  marco
 */
public class PnlDataCliente extends javax.swing.JPanel {
    /** Creates new form PnlDataCliente */
    public PnlDataCliente() {
        initComponents();
    }
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">
    private void initComponents() {
        bindingGroup = new org.jdesktop.beansbinding.BindingGroup();
        pnlInsertData1 = new
igest.gui.internal.components.PnlInsertData();
        jLabel1 = new javax.swing.JLabel();
        setLayout(new javax.swing.BoxLayout(this,
javax.swing.BoxLayout.LINE_AXIS));
 
pnlInsertData1.setBorder(javax.swing.BorderFactory.createTitledBorder("Data
inizio contratto"));
        add(pnlInsertData1);
        org.jdesktop.beansbinding.Binding binding =
org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE,
pnlInsertData1, org.jdesktop.beansbinding.ELProperty.create("$
{data}"), jLabel1,
org.jdesktop.beansbinding.BeanProperty.create("text"),
"ProvaConversione");
        binding.setSourceNullValue(null);
        binding.setSourceUnreadableValue(null);
        binding.setConverter(new DataConverter());
        bindingGroup.addBinding(binding);
        add(jLabel1);
    }// </editor-fold>
    // Variables declaration - do not modify
    private javax.swing.JLabel jLabel1;
    private igest.gui.internal.components.PnlInsertData
pnlInsertData1;
    private org.jdesktop.beansbinding.BindingGroup bindingGroup;
    // End of variables declaration
    private class DataConverter extends Converter<Date, String> {
        public String convertForward(Date data) {
            System.out.println("Forward");
            System.out.println(data != null);
            return "" + (data != null);
        }
        public Date convertReverse(String b) {
            // ritorno null perchè tanto la Jlabel del test non muterà
mai se non al mutare della data quindi...
            return null;
        }
    }
}
spero che possiate darmi una mano a capire cosa stò sbagliando.
Grazie 1000 a tutti in anticipo
Ciao Marco

 all'interno di un mio bean.artigianale.
Secondo me l'errore potrebbe essere nel tuo bean artigiale, faccelo vedere.
-- 
Andrea Francia
http://andreafrancia.blogspot.com/2008/07/colinux-linux-dentro-windows.html


In questo metodo devi chiamare firePropertyChange();
Però devi farlo anche nel tuo bean artigianale, usando la classe 
PropertyChangeSupport.
La documentazione di beansbinding non è molto chiara a riguardo, da per 
scontato che tutti conoscano a fondo i JavaBean.


> Secondo me l'errore potrebbe essere nel tuo bean artigiale, faccelo vedere.
Il mio bean "fatto in casa" è il PnlInsertData che ho inserito nel
primo post.
Ciao Marco

 scontato che tutti conoscano a fondo i JavaBean.
dici che è solo per il fatto che non chiamo il firePropertyChange()?
Grazie 1000 ancora
Marco

EVVIVA!!! Sono riuscito a fare andare il mio Bean artigianale!!!
Non ancora ben capito tutto il meccanismo che ci stà dietro al
funzionamento ma quello che importa è che ci sono riuscito e quindi
posso dedicarmi meglio alla teoria mentre continuo la trasformazione
del progetto che credo che oramai si traduce in una specie di copia-
incolla e sfoltimento delle dipendenze...
Un'ultima domanda, ma è possibile creare bindings con sorgente
multipla? Cioè sempre prendendo come esempio il mio bean PnlInsertData
potrei con un binding unire tutti e tre le JFormattedTextField? Oppure
devo continuare con l'evento e fare il binding solo sull'oggetto Date?
Grazie 1000 davvero
Ciao Marco

 Ciao Marco


 Definisci "continuare con l'evento".
Il continuare con l'evento è fare notificare tramite un PropertyEvent
il cambiamento di una proprietà.
Nel codice di gestione dell'evento ci saranno delle righe di codice
che varieranno una variabile di supporto, che anche questa dopo la
modifica genererà un evento PropertyEvent che a sua volta modificherà
lo stato di un componente.
Vedendo però adesso cosa mi permettono di fare i bindings mi sembra
veramente brutto creare delle catene di eventi....
Ciao Marco

 veramente brutto creare delle catene di eventi....
Boh, cosa sono le catene di eventi? Comunque basati dovresti dover 
risolvere tutto usando i PropertyChangeListeners.


 risolvere tutto usando i PropertyChangeListeners.
Catene di eventi perchè ogni evento che genero ne creerebbe un'altro,
in stile catena di sant'antonio...
Provo a vedere le EL eperando di non dover ancora rompere le scatole
Ciao e grassie dei consigli
Marco