How to tell if the mouse cursor is over a componen

2019-08-02 20:54发布

问题:

I'm trying to determine with the help of a mouse event if I'm over a specific component.

So right now I have two components, let's say buttonA and buttonB. ButtonA has a listener on it already listening for the mouse out event. ButtonB is flush against the edge of ButtonA.

I need to find out the code for it. Here is more details:

        protected function _mouseOutHandler(event:MouseEvent):void
        {
            if (data.subCategories.length>0)
            {
                if (MOUSE IS NOT OVER BUTTONB) {

                }

                if (MOUSE IS OVER DROPDOWNB) {

                }
            }
        }

回答1:

You can at any time determine what objects are under the mouse by using the DisplayObjectContainer#getObjectsUnderPoint() method. This function returns an Array of objects that lie under the specified point.

I you use it on the stage, it will return all the objects in the application that are under the point.

stage.getObjectsUnderPoint(new Point(mouseX, mouseY));

I guess that in your case it would suffice to only drill down from the container that holds the two Buttons.

myGroupWithButtons.getObjectsUnderPoint(new Point(mouseX, mouseY));

Note that a Button is itself an object that contains several other DisplayObjects and the function might thus return something like this:

myGroupWithButtons.myBtn.ButtonSkin8, [object Shape], [object Shape]

As you can see, in the case of a Spark Button it even lists the Button's skin rather than the Button itself. It's easy enough to get to the Button from there though.



回答2:

I didn't think you could figure this out using the event. The MouseEvent has the target (Component which dispatched the event) and currentTarget (component that added the listener); but in the case of the mouse out event; neither of those will be the item that the mouse is currently over; but rather the item the mouse used to be over.

A few options to consider:

1) Can you listen for the mouseOver event on the other components? If so, then you can use event.target. Something like this:

        protected function _mouseInHandler(event:MouseEvent):void
        {
            if (data.subCategories.length>0)
            {
//                if (MOUSE IS NOT OVER BUTTONB) {
                if (event.target is BUTTONB) {

                }

//                if (MOUSE IS OVER DROPDOWNB) {
                if (event.target is DROPDOWNB) {

                }
            }
        }

2) You might be able to loop over all children in the container and figure it out based on the localX and localY properties of the MouseEvent I'm not sure how good of an approach that is., In the mouseOut event, will the localX and localY properties show the coordinates where the mouse left the component--meaning they are still over the component, or will they show the coordinates where they entered the new component? Without testing I'm not sure. Also, I suspect this could be a performance drain.



回答3:

What I ended up doing (with inspiration from the above replies) is setting a timeout to give the mouse time to travel and then in that timeout handler using hitTestPoint to check if the mouse is over either components. Here is the code:

        private var timeout:uint;

        /**
         * On mouse out of item renderer set timeout 
         * */
        protected function _mouseOutHandler(event:MouseEvent):void {

            if (data.subCategories.length>0) {
                timeout = setTimeout(checkToClose, 150);
            }
        }

        /**
         * Handles when mouse moves out of drop down
         * */
        protected function _menuMouseOutHandler(event:MouseEvent):void {
            checkToClose();
        }

        /**
         * Check if mouse is out of drop down and category renderer
         * */
        public function checkToClose():void {
            var point:Point;

            clearTimeout (timeout);

            // check if drop down is open
            if (menu.dropDown) {
                point = localToGlobal(new Point(mouseX, mouseY));
                menu.dropDown.addEventListener(MouseEvent.MOUSE_OUT, _menuMouseOutHandler, false, 0, true);

                // check if we are over drop down or category renderer
                // if not close dropdown
                if (!menu.dropDown.hitTestPoint(point.x, point.y)
                    && !hitTestPoint(point.x, point.y)) {
                    menu.dropDown.removeEventListener(MouseEvent.MOUSE_OUT, _menuMouseOutHandler);
                    menu.closeDropDown(false);
                }
            }
        }