Firing Event if mouse enters graphic objects (figure, axes, button, etc.)
43 views (last 30 days)
One way to do this is to create a timer and define the graphics areas (in pixels or whatever) and timer keeps monitoring the mouse cursor, if it enters a component region (hovering) then it fires an event and then listener catches it and does something. The problem with this is that if the user resizes the GUI or move it, the timer needs to recalculate all again. I would like something more elegant, like for instant, Figure objects have a property called 'WindowMouseMovedEvent' but this is only for Figure objects. Is there anyway I can add a firing event to, say axes, and it will fire the event if the mouse enters the axes area? In Java, almost all objects have a Event if the mouse comes into contact with it (no clicking).
Geoff Hayes on 21 Feb 2016
Hi Alex - you can use the WindowButtonMotionFcn callback to determine which child uicontrol object (within the figure) is undergoing a mouse over event. Suppose we have a GUI with an axes and five pushbuttons. If the mouse is over the axes, we change its background colour to green. If the mouse is over a pushbutton, then we change its background colour to red. (This is just an example - you can do whatever you want, like fire your event to some listener.) Since the GUI is resizable, we will need the GUI (figure) position. In the WindowButtonMotionFcn callback, we do
figurePos = get(hObject,'Position');
% get the current position of the mouse
mousePos = get(hObject,'CurrentPoint');
mouseX = mousePos(1);
mouseY = mousePos(2);
We have the dimensions (from the position) of the figure and the current position of the mouse pointer. We then iterate over each child UI control within the figure as
hChildren = get(hObject,'Children');
hUiControl = hChildren(k);
% get the child position
uiControlPos = get(hUiControl,'Position');
% create the x and y lower (L) and upper (U) bounds (we assume that the
% GUI is resizeable so the child position array contains proportions
% relative to the parent GUI)
uiControlXL = uiControlPos(1)*figurePos(3);
uiControlXU = (uiControlPos(1)+uiControlPos(3))*figurePos(3);
uiControlYL = uiControlPos(2)*figurePos(4);
uiControlYU = (uiControlPos(2)+uiControlPos(4))*figurePos(4);
% check to see if the mouse is over the control
if mouseX>=uiControlXL && mouseX<=uiControlXU && ...
mouseY>=uiControlYL && mouseY<=uiControlYU
% do something
In the do something above we can set the colour of the UI control that is undergoing the mouse over event. See the attached for an example
More Answers (1)
Walter Roberson on 21 Feb 2016
At least up to R2014a, there is an undocumented routine that makes your life easier. Up to that version (no idea about later), look for example in the source for datacursormode near line 780, at function localWindowMotionFcn . Apparently there is an undocumented routine hittest(), and if you pass in the handle of your current figure, it will return the handle of the object under the current point.
Be sure to use this under a WindowButtonMotionFcn rather than a *ButtonDownFcn as those latter only activate upon click of a pickable hittest-able object .
Ah, there is a limitation for this: hittest() will not register objects whose Hittest property is off. But checking, I see that if you give hittest() the option 'axes' then handle() of the axes will be returned even if the axes has hittest off. Or at least so it goes up to R2014a.