Lemur: listening for changes to TextField

I’m using Lemur. It’s excellent. Way better than Nifty (IMO). The documentation … not so much. I notice that much of it is editable so I’d like to see if I can improve it as I find stuff out to help other newbies.

Is there an easy way to be notified when the content of a TextField changes? I assumed it’d either be extending DocumentModel or adding a listener but I couldn’t get either approach to work. The document model approach seems to require overriding everything that might change the text rather than just setText.

My current solution is to update the field based on the text in the update method of the AppState that owns the TextField. That seems pretty inefficient given the text changes rarely.

Does anyone have some good sample code for this?

Since JME apps are constantly polling, Lemur tends to use the lighter-weight approach of using VersionedReference to watch things for changes. It’s what all of the other components are probably doing anyway.

VersionedReference docRef = myTextField.getModel().createReference();

...then in your update somewhere that wants to know when it has changed:

if( docRef.update() ) {
    // Do some things with docRef.get().getText() or whatever
}

docRef.update() is just an == check between two longs. It’s very fast.

The nice thing about the reference approach is that there are no listeners to clean up or anything. (It’s a near-constant debugging nightmare to figure out what thing hasn’t removed its listener from what Swing component that ends up with 10,000 listeners for a long-running app… never mind the duplication of the listener lists, etc. necessary to have mutable listener lists during iteration and so on.)

…listeners can be pretty expensive on their own, even called rarely.

VersionedRef on the other hand is free to be GC’ed whenever you stop using it. The versioned object has no idea about it and doesn’t need to care. And since we’re already polling all the time, the normal down side to something like this goes away.

The other nice thing is that you don’t waste events telling listeners about every single change when they only really want “something has changed since last time”.

If you really must be notified about every change then you can extend DocumentModelFilter and override filterInput() or filterOutput(), depending on your need. Then you will be notified about every little thing and can do what you need to with that.

3 Likes

That makes perfect sense and is a good approach.

Thanks for your help.

Added some doc at Modules · jMonkeyEngine-Contributions/Lemur Wiki · GitHub.

3 Likes