[SOLVED] Need help with adding mouse listener to ListBox

Hi

I started to apply some Tween animation to my WIP inventory.
Adding a mouse listener to listbox I am having an issue :

Hovering mouse on element in the listbox exit it’s listener. (call mouseExited of listbox mouse listener)

So just want to know what is the smarter way to solve this ?

Should I also add listener to each element in listbox ?
Should I add an invisible box geometry which has grater Z offset than other elements to container and add the listener to it (similar to what is done in DragAndDropDemoState) ?

Here is the code:

    @Override
    protected void initialize(Application app) {

            //Add Tween animation effects to our GUI elements

            //for SystemsWindow
            Vector3f systemWindowStart = systemsWindow.getLocalTranslation().clone();
            Vector3f systemWindowEnd = systemWindowStart.add(0, -systemsWindow.getPreferredSize().x, 0);

            //Add open/close effect to container which contains ListBox
            systemsWindow.addEffect("open", createMoveEffect("open/close", null, systemWindowEnd, 0.5f));
            systemsWindow.addEffect("close", createMoveEffect("open/close", null, systemWindowStart, 0.5f));
            //FIXME: adding mouse enter/exit listener to ListBox 
            systemTray.addMouseListener(new OpenCloseEffectListener());
}
        /**
         * Listens for enter/exit events and run the tween effect accordingly.
         */
        private class OpenCloseEffectListener extends DefaultMouseListener {
         
            public void mouseEntered(MouseMotionEvent event, Spatial target, Spatial capture) {
                //This spatial is the ListBox and we need to get it's parrent 
                // which is the container we added animation effect on it
                // then run the effect.
                ((Panel)target.getParent()).runEffect("open");
            }

            public void mouseExited(MouseMotionEvent event, Spatial target, Spatial capture) {
                ((Panel)target.getParent()).runEffect("close");
            }
        }

The issue is that only one ‘thing’ can be ‘entered’ at any given time. Generally, a useful idea but it kind of gets tricky when you want to know entered/exited for a whole hierarchy. I’ve been trying to think of a good solution for these cases… so far the best I’ve come up with is to treat hover like focus or to give enter/exit its whole hierarchy management like focus management does. There are some unappealing aspects in both cases.

Likely, the list items are regular Buttons and so will consume the entered/exited events. That’s what lets them highlight when you hover over them.

Probably the easiest way is to register a listener with each item. You can either do that in a custom cell renderer (just remember not to do it when the item is reused) or override ListBox’s protected getListCell() method which is basically what calls the factory.

The trick in both cases is that you won’t easily be able to go back and remove the listeners once added. Which is only a problem if they are well linked in with the rest of the object graph. If their own context lives/dies with the ListBox then it’s probably fine.

On my end, perhaps an interim solution that also isn’t “wrong” in the future would be to add actions for item enter/exit like buttons have. Actually, now that I look at the code, I do have enter/exit for effects.

Are you doing this with Effects? If so then an easier ultimate solution for you would be to have me make the list-wide enter/exit effect triggering be accurate.

Never mind
I just added the same listener for all listbox elements (including Slider).
Everything works fine now. And

And sorry for bothering. :sweat_smile:

@pspeed you posted a few seconds earlier than my post.

Yes .

No… it’s a valid issue. You shouldn’t have had to struggle with this as it should have just been a matter of adding an entered/existed effect.

…if you aren’t using effects in this case then you probably should be. They were specifically designed to trigger animations, after all. :slight_smile:

Edit: you ninja’d me on the response.

Well, that’s good… so if I fix the effects then you can remove your hack someday.

Doesn’t this relate to event bubbling @pspeed ? Usually they all bubble up the hierarchy unless you set some sort of flag. In C# there was a .preventDefault() method on the event to stop it bubbling up if you didn’t want that behavior, else it would do so by default.

I mean, there are two things here:

  1. what hierarchy? The listeners are just added to regular old spatials… which may or may not be part of a UI hierarchy. (And by the way, unconsumed events do propagate up… even in swing if the events are consumed then they don’t propagate.)
  2. this is enter/exit state, not just some single event. You will never ever get an exit unless you also got an enter. And if you got an enter, you are guaranteed to eventually get an exit… unless you close the app. So “propagation” in this case requires a whole hierarchy of tracked state… just like focus management.

None of this is very appealing in light of trying to keep things simple. Especially since it almost never comes up.

I’ve just checked in some ListBox changes that should allow the activation/deactivation effects to trigger properly in most cases. (Doesn’t yet work over the scroll bar.) The ListAction.Entered and ListAction.Exited should also work as expected. (same scroll bar caveat applies).

Closer.

I’ve a mouse/cursor event refactoring on my plate from some time back that might affect these cases so I don’t want to dive too much deeper than that.

1 Like

Thanks so much Paul,
I am going to test it.

Okay tested it and it works fine. Thanks.
I am using effect listener one

        //Adding mouse enter/exit effect to ListBox 
        systemTray.addEffect(ListBox.EFFECT_ACTIVATE, createMoveEffect("open/close", null, systemWindowEnd, 0.5f, systemsWindow));
        systemTray.addEffect(ListBox.EFFECT_DEACTIVATE, createMoveEffect("open/close", null, systemWindowStart, 0.5f, systemsWindow));

For now I am just keeping the listeners for Slider.

Glad it works. I’m looking to push out the new release soon and didn’t want last-minute mistakes holding things up. :slight_smile:

1 Like