I need to enable and disable events from firing in a JList where I am dynamically changing the contents. I want to disable events when changing list contents, but enable them to get user selection. If I don't disable them, then the action of dynamically changing contents fires a 'value changed' event and so the 'getSelectedIndex' is set inappropriately. OpsTool.java [451:1] enableEvents(long) has protected access in java.awt.Component HostList.enableEvents(AWTEvent.ITEM_EVENT_MASK); ^ OpsTool.java [467:1] disableEvents(long) has protected access in java.awt.Component HostList.disableEvents(AWTEvent.ITEM_EVENT_MASK);
I don't think temporarily removing the Listener works.
You remove the Listener, then make the change. The change causes an Event to be put in the Event Queue. You complete your change, reinstall the Listener, and return. Now the Event Multicaster takes over and sends the Event to your Listener - At least this seemed to be what happened when I tried it with a ComponentListener that I was using to monitor the size of a JFrame.
My (not very nice) solution is to save the start time:
and then ignore events until isCascading() returns false
Sorry to take 10 years to add this comment!!!
You wait all this time for a coincidence, then two come along at once...
Your code may not be correctly respecting Swing's single threaded rule. Even if it does, it's sometimes necessary to wrap user customizations in a SwingUtilities#invokeLater(...) to achieve the desired event notification sequence.
I much prefer the idiom of maintaining a boolean flag the value of which is tested in event handling code. That approach is immune to concurrency issues.
There are no new questions, but there may be new answers.
Joined: Nov 09, 2008
Thanks for your comments.
Sorry, I wasn't clear. I'm not removing/adding the Listener, just making the Listener ignore callbacks. The set/isCascading calls are all from the componentResized call, so are only called during callbacks which are on the Swing thread. I don't think that violates the single threaded rule, but I've now inserted to check.
This solution doesn't rely on event timing - just a sledge-hammer 100 millisecond dead time.
(I'm not particularly defending it, just trying to learn)
Two things I don't like about the above solution: firstly the frequent calls to the real time clock, and secondly the arbitrary 100 milliseconds.
It would be cleaner if I could remove the listener, and then put a SwingWorker on the end of the Event Queue and use that to re-add the Listener - is InvokeLater guaranteed to be invoked after all pre-existing Events? Have just looked it up. I see that this is the case.