Crear evento propio
Hola a todos. Mi duda es la siguiente. Me gustarÃa saber, si es posible, como puedo crear un evento o un listener propio. Lo intentaré explicar con un ejemplo:
Yo tengo una variable,la cual quiero controlar que llegue hasta un determinado valor. Este valor puede ir cambiando cuando pinche en un botón o en un campo de texto,por ejemplo. Lo que quiero es crear una especie de Listener que me vaya comprobando la variable hasta que llegue a un determinado valor. ¿SerÃa posible? Muchas gracias.
Yo tengo una variable,la cual quiero controlar que llegue hasta un determinado valor. Este valor puede ir cambiando cuando pinche en un botón o en un campo de texto,por ejemplo. Lo que quiero es crear una especie de Listener que me vaya comprobando la variable hasta que llegue a un determinado valor. ¿SerÃa posible? Muchas gracias.
Hola
Por supuesto que sÃ. Supongo que tu variable será miembro de alguna clase.
Debes seguir el modelo de eventos de Java descrito en el AWT.
Una clase es fuente de un evento y una o más clases pueden declararse como oyentes de ese evento. Estas clases oyentes pueden ser de los tipos más dispares, pero todas ellas deben implementar la interfaz que las define como posibles oyentes del evento. En este ejemplo, esta interfaz se llamará VariableChangeListener:
import java.util.*;
public interface VariableChangeListener {
public void variableChanged(EventObject e);
}
Como puedes ver, esta interfaz sólo obliga a implementar un método, variableChanged, al que se llamará cuando se lance el evento. Este método recibe un único argumento, de tipo java.util.EventObject, que representa un objeto de estado de evento. Su función es identificar al objeto fuente del evento.
Si deseas que el objeto de estado del evento proporcione más información, te haces una subclase de ésta y ya está.
La interfaz Listener podrÃa definir tantos métodos como eventos distintos pudiesen diferenciarse. En caso de haber un número excesivo de eventos, serÃa interesante crear una clase adaptadora. Pero no me meto en este jardÃn, porque nuestra interfaz sólo define un método.
Asà que todas las clases que quieran apuntarse como oyentes del evento tendrán que implementar esta interfaz.
Por ejemplo, la clase MiClase quiere atender a eventos de este tipo:
public class MiClase implements VariableChangeListener {
...
// En algún método esta clase se registra como oyente
Variable var;
...
var.addVariableChangeListener(this);
// Debe implementar el método definido por la interfaz
public void variableChanged(EventObject evt) {
// Y actuar en consecuencia al dispararse el evento
}
...
}
Bueno, y ahora queda lo divertido, que es implementar la clase fuente del evento. Es muy facilote, verás: esta clase tiene una única variable miembro (aquella cuyo valor queremos controlar). Cuando se le dé a esta variable un valor superior al lÃmite establecido, se disparará el evento.
La clase fuente de evento debe implementar dos métodos para registrar y desregistrar oyentes del evento. El registro de un oyente, addVariableChangeListener, se limita a agregar al mismo (un objeto que, recordemos, implementa la interfaz antes definida) a una lista de oyentes. El desregistro, removeVariableChangeListener, obviamente elimina al oyente de tal lista (un objeto podrÃa querer dejar de ser notificado de ese evento).
También implementa un método protegido (sólo lo llama la propia clase fuente o una hipotética subclase) al que se llama desde cualquier método que modifique el valor de la variable a controlar cuando supere el valor lÃmite: notifyVariableChanged.
Te pongo la clase:
import java.util.*;
public class Variable {
private static int LIMITE_SUP;
private int variable;
private List listeners = new ArrayList();
// Métodos accesores
public void setVariable(int variable) {
this.variable = variable;
if (this.variable > LIMITE_SUP)
notifyVariableChanged();
}
public int getVariable() {
return this.variable;
}
// Métodos de registro/desregistro de oyentes
public synchronized void addVariableChangeListener(VariableChangeListener listener) {
listeners.add(listener);
}
public synchronized void removeVariableChangeListener(VariableChangeListener listener) {
listeners.remove(listener);
}
// Método de notificación de evento
protected void notifyVariableChanged() {
List lst;
EventObject evt = new EventObject(this);
synchronized(this) {
lst = (List)((ArrayList)listeners).clone();
}
for (Iterator it = lst.iterator() ; it.hasNext() ; )
((VariableChangeListener)it.next()).variableChanged(evt);
}
}
Un breve comentario sobre los métodos de registro/desregitro y el de notificación de evento: los dos primeros son sincronizados, porque se supone que se les puede invocar desde distintos objetos simultáneamente y hay que evitar pollos. El último parece complicado, pero no lo es en absoluto: se limita a invocar al método variableChanged sobre todos los objetos que hay en la lista de oyentes registrados. Pero no recorre esa lista directamente, sino un clon de la misma. AsÃ, no hay problemas si, por ejemplo, estamos recorriendo el iterador procedente de la lista y se nos registra o desregistra un nuevo objeto como oyente del evento.
Y nada más. Espero haberme explicado con claridad. Cualquier duda, plantéala en este mismo foro.
Salud
David
Por supuesto que sÃ. Supongo que tu variable será miembro de alguna clase.
Debes seguir el modelo de eventos de Java descrito en el AWT.
Una clase es fuente de un evento y una o más clases pueden declararse como oyentes de ese evento. Estas clases oyentes pueden ser de los tipos más dispares, pero todas ellas deben implementar la interfaz que las define como posibles oyentes del evento. En este ejemplo, esta interfaz se llamará VariableChangeListener:
import java.util.*;
public interface VariableChangeListener {
public void variableChanged(EventObject e);
}
Como puedes ver, esta interfaz sólo obliga a implementar un método, variableChanged, al que se llamará cuando se lance el evento. Este método recibe un único argumento, de tipo java.util.EventObject, que representa un objeto de estado de evento. Su función es identificar al objeto fuente del evento.
Si deseas que el objeto de estado del evento proporcione más información, te haces una subclase de ésta y ya está.
La interfaz Listener podrÃa definir tantos métodos como eventos distintos pudiesen diferenciarse. En caso de haber un número excesivo de eventos, serÃa interesante crear una clase adaptadora. Pero no me meto en este jardÃn, porque nuestra interfaz sólo define un método.
Asà que todas las clases que quieran apuntarse como oyentes del evento tendrán que implementar esta interfaz.
Por ejemplo, la clase MiClase quiere atender a eventos de este tipo:
public class MiClase implements VariableChangeListener {
...
// En algún método esta clase se registra como oyente
Variable var;
...
var.addVariableChangeListener(this);
// Debe implementar el método definido por la interfaz
public void variableChanged(EventObject evt) {
// Y actuar en consecuencia al dispararse el evento
}
...
}
Bueno, y ahora queda lo divertido, que es implementar la clase fuente del evento. Es muy facilote, verás: esta clase tiene una única variable miembro (aquella cuyo valor queremos controlar). Cuando se le dé a esta variable un valor superior al lÃmite establecido, se disparará el evento.
La clase fuente de evento debe implementar dos métodos para registrar y desregistrar oyentes del evento. El registro de un oyente, addVariableChangeListener, se limita a agregar al mismo (un objeto que, recordemos, implementa la interfaz antes definida) a una lista de oyentes. El desregistro, removeVariableChangeListener, obviamente elimina al oyente de tal lista (un objeto podrÃa querer dejar de ser notificado de ese evento).
También implementa un método protegido (sólo lo llama la propia clase fuente o una hipotética subclase) al que se llama desde cualquier método que modifique el valor de la variable a controlar cuando supere el valor lÃmite: notifyVariableChanged.
Te pongo la clase:
import java.util.*;
public class Variable {
private static int LIMITE_SUP;
private int variable;
private List listeners = new ArrayList();
// Métodos accesores
public void setVariable(int variable) {
this.variable = variable;
if (this.variable > LIMITE_SUP)
notifyVariableChanged();
}
public int getVariable() {
return this.variable;
}
// Métodos de registro/desregistro de oyentes
public synchronized void addVariableChangeListener(VariableChangeListener listener) {
listeners.add(listener);
}
public synchronized void removeVariableChangeListener(VariableChangeListener listener) {
listeners.remove(listener);
}
// Método de notificación de evento
protected void notifyVariableChanged() {
List lst;
EventObject evt = new EventObject(this);
synchronized(this) {
lst = (List)((ArrayList)listeners).clone();
}
for (Iterator it = lst.iterator() ; it.hasNext() ; )
((VariableChangeListener)it.next()).variableChanged(evt);
}
}
Un breve comentario sobre los métodos de registro/desregitro y el de notificación de evento: los dos primeros son sincronizados, porque se supone que se les puede invocar desde distintos objetos simultáneamente y hay que evitar pollos. El último parece complicado, pero no lo es en absoluto: se limita a invocar al método variableChanged sobre todos los objetos que hay en la lista de oyentes registrados. Pero no recorre esa lista directamente, sino un clon de la misma. AsÃ, no hay problemas si, por ejemplo, estamos recorriendo el iterador procedente de la lista y se nos registra o desregistra un nuevo objeto como oyente del evento.
Y nada más. Espero haberme explicado con claridad. Cualquier duda, plantéala en este mismo foro.
Salud
David
La solucion es bastante simple, mira... como sabemos un objeto es un elemento de softaware que tiene estado y comportamineto
por ejemplo crearemos un JFrame con un boton que valla cambiando que diga fui presionado
public class Aplicacion{
public static void main(String[] a){
Ventana v = new Ventana();
}
}
//---------------------------------------------------
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class Ventana extends JFrame{
static JButton boton;
static int i=0;
static JLabel label;
static JPanel panel;
ActionListener evento = new Control();
public Ventana() {
super();
this.setVisible(true);
this.setTitle("Programa de muestra..... by rolextreme");
this.setSize(350,70);
this.setLocation(200,50);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container c = getContentPane();
panel= new JPanel();
boton = new JButton("START");
label = new JLabel("Fui presionado "+i);
panel.add(boton);
panel.add(label);
c.add(panel,BorderLayout.CENTER);
show();
escucha();
}
public void escucha(){
boton.addActionListener(evento);
}
private class Control implements ActionListener{
public void actionPerformed(ActionEvent a) {
if(boton==a.getSource()){
i++;
label.setText("Fui presionado "+i);
}
}
}
}
Sigue esta arquitectura, te explico, cree una clase privada para capturar los eventos con una mayor precision, luego los instancie atravez del metodo escucha, bueno, es mi manera de programacion, es mas elegante y ademas mas efectiva, sigue esta arquitectura... el programa solo hace que cuando precionas un boton se incrementa un contador, espero haber sido de ayuda y que mi solucion sea de tu agrado.
Atentamente
rolextreme
por ejemplo crearemos un JFrame con un boton que valla cambiando que diga fui presionado
public class Aplicacion{
public static void main(String[] a){
Ventana v = new Ventana();
}
}
//---------------------------------------------------
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class Ventana extends JFrame{
static JButton boton;
static int i=0;
static JLabel label;
static JPanel panel;
ActionListener evento = new Control();
public Ventana() {
super();
this.setVisible(true);
this.setTitle("Programa de muestra..... by rolextreme");
this.setSize(350,70);
this.setLocation(200,50);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container c = getContentPane();
panel= new JPanel();
boton = new JButton("START");
label = new JLabel("Fui presionado "+i);
panel.add(boton);
panel.add(label);
c.add(panel,BorderLayout.CENTER);
show();
escucha();
}
public void escucha(){
boton.addActionListener(evento);
}
private class Control implements ActionListener{
public void actionPerformed(ActionEvent a) {
if(boton==a.getSource()){
i++;
label.setText("Fui presionado "+i);
}
}
}
}
Sigue esta arquitectura, te explico, cree una clase privada para capturar los eventos con una mayor precision, luego los instancie atravez del metodo escucha, bueno, es mi manera de programacion, es mas elegante y ademas mas efectiva, sigue esta arquitectura... el programa solo hace que cuando precionas un boton se incrementa un contador, espero haber sido de ayuda y que mi solucion sea de tu agrado.
Atentamente
rolextreme