Foro sobre Java SE > Duda sobre JavaBeans Urgente.
La manera más simple de hacerlo es con un Property Change Listener:
Desde el ActionPerformed del botón se dispara un PropertyChangeListener del contenedor, Calendario, que supongo será un JPanel, con los datos que se quieran propagar: ese String o Date con la fecha.
En el JFrame que inicializa el Calendario, una instancia de éste último registra un PropertyChangeListener.
Como este tipo de listener usa un String como identificador de eventos, es fácil conocer cuál se ha disparado desde el botón, y procesarlo como convenga en el JFrame.
http://docs.oracle.com/javase/tutorial/uiswing/events/propertychangelistener.html
Sí así es como lo he hecho...pero pasa de mi...no entra al addPropertyChangeListener.
Yo he hecho lo siguiente, a ver si ves el fallo y me puedes ayudar:
Dentro del JavaBean, a cada JToggleButton (representa el día del mes), les asocio un ActionListener, dentro del cual hago un setFechaActual, actualizo mi atributo fechaActual al dia que ha seleccionado, y dentro de ese setFechaActual llamo al método firePropertyChangeListener(nombrePropiedad, fechaAntigua,fechaNueva).
Luego dentro del otro proyecto de Prueba...tengo un JFrame y dentro de el mi javabean MiJCalendario y un label por ahí suelto en el frame. A este frame le he añadido un escuchador de propiedad (this.addPropertyChangeListener) y le he pasado un objeto anónimo de PropertyChangeListener, donde implemento su método propertyChange y dentro de él hago que se actualice el JLabel con la fecha actual del calendario...pero nunca entra a ese método, es decir nunca escucha nada....
¿dónde podría estar el fallo?
Te pego el código del JFrame de prueba donde tengo alojado el calendario:
java.beans.PropertyChangeSupport propertyChangeSupport = new java.beans.PropertyChangeSupport(this);
public PruebaMiJCalendario() {
initComponents();
System.out.println(miJCalendario2.getFechaActual());
propertyChangeSupport.addPropertyChangeListener("fechaActual", new PropertyChangeListener(){
@Override
public void propertyChange(PropertyChangeEvent evt) {
System.out.println("aqui"+miJCalendario2.getFechaActual());
jLabel1.setText(miJCalendario2.getFechaActual());
}
});
Gracias.
Saludos
Lo solucione...uffffffffff llevo un par de horas desquiciado...
mi fallo era que tenía dos objetos propertyChangeSupport, uno en el Bean y otro en el JFrame de prueba, uno asociado al JPanel del JavaBean y el otro asociado al JFrame del proyecto prueba, entonces uno lanzaba eventos propertychange pero no habia nadie en ese propertyChangeSupport escuchando...
He hecho un get del propertyChangeSupport del Bean y lo uso en el JFrame de prueba, y allí le añado la propiedad, ya que quiero actualizar un JLabel del Frame del proyecto prueba...no se si lo estoy haciendo correctamente..pero funciona.
Saludos.
El PropertyChangeSupport solo se usa cuando la clase no lo tiene por defecto. Con componentes de Swing no es necesario.
Por otra parte, siempre hay que tener mucho cuidado sobre quién dispara y quién recibe los eventos.
Es fácil confundirse y disparar el evento del PropertyChange del botón, en vez del contenedor, si se usan clases anónimas para los ActionListener, por ejemplo.
En el JFrame, quién debe registrar los eventos es la instancia de la clase Calendario, que si es un componente de Swing ya tiene incluido el PropertyChangeSupport.
Pues si hago que el MiJCalendario lo haga, tanto los dispare como los llame el...no me hace ni caso.....solo lo consigo si voy pasando el objeto PropertyChangeSupport...¿cómo lo podría simplificar?
public class Panel extends javax.swing.JPanel {
/** Creates new form Panel */
public Panel() {
initComponents();
jButton1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Panel.this.firePropertyChange("boton1", null, "Soy el boton 1");
}
});
jButton2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Panel.this.firePropertyChange("boton2", null, "Soy el boton 2");
}
});
}
/** 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() {
jButton1 = new javax.swing.JButton();
jButton2 = new javax.swing.JButton();
jButton1.setText("jButton1");
add(jButton1);
jButton2.setText("jButton2");
add(jButton2);
}// </editor-fold>
// Variables declaration - do not modify
private javax.swing.JButton jButton1;
private javax.swing.JButton jButton2;
// End of variables declaration
}
public class Frame extends javax.swing.JFrame {
public Frame() {
initComponents();
jPanel1.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
switch (evt.getPropertyName()) {
case "boton1":
System.out.println(evt.getNewValue());
break;
case "boton2":
System.out.println(evt.getNewValue());
break;
}
}
});
}
/** 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() {
jPanel1 = new Panel();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER);
pack();
}// </editor-fold>
/**
@param args the command line arguments
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new Frame().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JPanel jPanel1;
// End of variables declaration
}
Ese es un ejemplo ejecutable que muestra la manera de lograrlo.
Muchas gracias choces...no sé porque no me iba antes...o qué estaba haciendo mal...pero he hecho que al firePropertyChange lo llame this, es decir, el JPanel del JavaBean, y que al addPropertyChangeListener lo llame el propio JavaBean, y ya me funciona perfectamente.......uffffff cuando te ofuscas pues...pierdes un poco de tiempo.
Gracias de nuevo!
Saludos.
Una duda que me viene a la mente....realmente tendría más lógica que las propiedades que tienen que escuchar...se las añadiésemos al componente destino del evento...en este caso el JLabel...es decir, deberia llamar al addPropertyChangeListener() el jLabel y no el JavaBean...y el JavaBean llamar al firePropertyChange, que es la fuente de los eventos...y los componentes (en este caso el JLabel) estar a la escucha de cualquier evento que se lance del tipo propertyChangeEvent....no????No me queda muy claro que el JavaBean sea tanto fuente como destino de este tipo de eventos.
Saludos.
En ese caso el JLabel debería ser visible fuera del contenedor, para poder registrar sus propios eventos.
Es una cuestión de encapsulación: si el contenedor es el único visible, debe procesar todos los eventos que lancen sus componentes internos.
El problema de hacer accesibles los componentes, es que puede modificarse su comportamiento desde cualquier clase que los "vea", tanto intencionadamente como por error.
Puesto que los PropertyChangeListener tienen una "etiqueta", es fácil conocer qué componente los ha disparado. El hecho de que los eventos los registre el contenedor, no le convierte en "propietario" de los mismos, sino en un vehículo para su procesamiento.
Por todo ello, es perfectamente lógico que haya un único registro de eventos por parte del contenedor, para mantener la correcta encapsulación de sus componentes internos, que a su vez también son propiedades privadas del contenedor.
En realidad, cuando el contenedor dispara un evento, lo que hace es exponer al exterior (mediante su listener), que una propiedad suya (un componente en este caso) ha cambiado.
He vuelto a releer todos los comentarios, porque algo no me cuadraba del todo.
Ese JLabel que mencionas está en el JFrame, por lo que he leído, y no forma parte del contenedor del Calendario.
En este caso, no tiene sentido que el JLabel registre su propio listener para escuchar eventos del Calendario, porque no tiene ninguna relación con él.
El objeto del PropertyChangeListener es que una clase pueda escuchar eventos propios desde sus instancias en otras clases diferentes, por las razones expuestas en el comentario anterior.
Si ese JLabel es ajeno al contenedor Calendario, no puede escuchar eventos disparados en éste último.
Si el JLabel necesita modificarse, en función de eventos de Calendario, debe hacerlo dentro del listener de Calendario, que es quien "comunica" a la clase donde está instanciado, el JFrame, que sus propiedades han cambiado.
Sí eso es lo que yo había entendido haciéndolo...pero pensaba que al hacer el firePropertyChange el Calendario...si algún elemento que estuviera declarado donde se ha declarado el Calendiario, el Frame, llamaba al método addPropertyChangeListener, pensaba que se quedaría escuchando algún cambio de la propiedad con nombre X, que coincide con el nombre de la propiedad que usa el firePropertyChange. Sería una pasada si hiciera eso jeje
No, eso no lo hace Swing, ni el JDK. No disponen de un "buzón global" donde enviar mensajes y desde donde recibirlos.
Eso lo hacen librerías externas como EventBus, o Guava (más limitado que EventBus), que implementan el patrón Publisher/Subscriber.
Hola a tod@s,
he hecho un javabean..que es un Calendario...de manera visual, se compone de los dias del mes que son botones, un spìnner para los años y un combobox para los meses.
Va todo perfecto...pero tengo una duda...Ya incorporo el Bean en la paleta del Netbeans, todo perfecto..pero me interesa que cada vez que hagan clic en uno de los botones, retornase la fecha actual en un String mismo, o Date, me da igual. La cuestión es que no se cómo hacerlo...cómo le asocio un evento a ese componente que cada vez que haga clic en un botón, devuelva al frame que solo contiene el componente MiJCalendario (bean propio) la fecha...tengo el método getFecha en el componente...pero tengo que asociar eventos a ese Bean desde un Frame que solo contiene el JavaBean...nada más...
Gracias.
Saludos.