简体   繁体   中英

Java PropertyChangeListener

I'm trying to figure out how to listen to a property change in another class. Below is my code:

ClassWithProperty has the property I want to listen to:

public class ClassWithProperty {
    private PropertyChangeSupport changes = new PropertyChangeSupport(this); 
    private int usersOnline;

    public int getUsersOnline() {
        return usersOnline;
    }

    public ClassWithProperty() {
        usersOnline = 0;
        while (usersOnline<10) {
            changes.firePropertyChange("usersOnline", usersOnline, usersOnline++);
        }
    }

    public void addPropertyChangeListener(
        PropertyChangeListener l) {
        changes.addPropertyChangeListener(l);
    }
    public void removePropertyChangeListener(
        PropertyChangeListener l) {
        changes.removePropertyChangeListener(l);
    }
}

Main is where i need to know about the property change:

public class Main {

    private static ClassWithProperty test;

    public static void main(String[] args) {
        test = new ClassWithProperty();
        test.addPropertyChangeListener(listen());

    }

    private static PropertyChangeListener listen() {
        System.out.println(test.getUsersOnline());
        return null;
    }

}

I have the event fired only the last time (usersOnline=10). I'm new to Java and tried to find a solution, but to no avail.

The code:

private static PropertyChangeListener listen() {
    System.out.println(test.getUsersOnline());
    return null;
}

returns null which means "no object", which in turn means that test.addPropertyChangeListener(listen()) is effectively test.addPropertyChangeListener(null) , which won't register anything.

You must pass a valid instance of a PropertyChangeListener to the addPropertyChangeListener() method.

Edit

I suggest you read the Java tutorial's chapter about PropertyChangeListeners:
http://download.oracle.com/javase/tutorial/uiswing/events/propertychangelistener.html

Another problem of your code is that you call firePropertyChange() in the constructor of ClassWithProperty . But at that time, no listener can possibly be registered, so it does not have any effect. Any call to addPropertyChangeListener() happens after you have fired the events.

Here is your code modified so that it should work (haven't tested it though...):

public class ClassWithProperty {
    private PropertyChangeSupport changes = new PropertyChangeSupport(this);
    private int usersOnline = 0;

    public ClassWithProperty() {
    }

    public void setupOnlineUsers() 
    {
        while (usersOnline < 10) {
            changes.firePropertyChange("usersOnline", usersOnline, ++usersOnline);
        }
    }

    public int getUsersOnline() {
        return usersOnline;
    }

    public void addPropertyChangeListener(PropertyChangeListener l) {
        changes.addPropertyChangeListener(l);
    }

    public void removePropertyChangeListener(PropertyChangeListener l) {
        changes.removePropertyChangeListener(l);
    }
}

public class MainListener implements PropertyChangeListener {
    private ClassWithProperty test;

    public MainListener() {
        test = new ClassWithProperty();
        test.addPropertyChangeListener(this);
        test.setupOnlineUsers();
    }

    public void propertyChange(PropertyChangeEvent evt) {
        System.out.println(test.getUsersOnline());
    }

    public static void main(String[] args) {
        new MainListener(); // do everything in the constructor
    }
}

What I do is put a method in the ClassWithProperty class:

public PropertyChangeSupport getPropertyChangeSupport() {
    return changes;
}

Then, register for property change events in the constructor of your Main() class:

private void initializeListeners() {
    test.getPropertyChangeSupport().addPropertyChangeListener((PropertyChangeEvent event) -> {
        if (event.getPropertyName().equals("usersOnline"))   {
            String passedEventData = (String) event.getNewData(); 
        }
    });
}

This make it so you are not repeating the code in your ClassWithProperty with methods that are already in the PropertyChangeSupport class.

when you need to fire an event in your ClassWithProperty class, do:

changes.firePropertyChange("usersOnline", oldValue, newValue);

One notable feature of this method is that, if the
event.getOldValue() and the event.getNewValue() are equal, the event will not fire. If you want to fire repeated events with the same information, use null in the oldValue field; The firePropertyChange() method only passes int, boolean and Object. So if you are not passing an int or boolean, you need to cast the value that was passed in the event on the receiving end.

Your method here:

public ClassWithProperty() {
    usersOnline = 0;
    while (usersOnline<10) {
        changes.firePropertyChange("usersOnline", usersOnline, usersOnline++);
        usersOnline++;
    }
}

has a while loop that will continuously loop and block the thread. My limited knowledge of property change listeners is that they listen for changes to a bound property, here the usersOnLine variable, meaning the property change should only fire if this number changes (likely within in any setUserOnLine , addUserOnLine , removeUserOnLine and similar methods). For more on bound properties, please look here: Bound Properties

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM