admin管理员组文章数量:1359409
Preamble
Some time ago, I created an application in matlab where I could move/rotate some object directly from the mouse (i.e. some kind of mini-cadtool interface):
I created the application on the go and was directly attaching to WindowButtonMotionFcn
callback in figure
properties and using the undocumented hittest
function to detect objects below the mouse and everything was fine ...
Now I would like to rework this code to extract cad-manipulation part to some sort of uicad
object just like we can have uicontrol
, uipanel
, etc... so I can use it as component on the shelf and plug it in any figure I want.
Especially I wanted not to directly modify WindowButtonMotionFcn
of the parent figure ... Indeed, if I want to do something modular, I cannot guarantee that this callback is not already in use (or will be in use) by someone else.
I then figured out that I could use equivalent WindowMouseMotion
event in figure
object so this way it is possible to attach as many event listeners as we want (see addlistener
) without disturbing other listeners or even disturbing the WindowButtonMotionFcn
property itself (which support only one listener).
Problem
Unfortunately when using event
instead of callback
(which obviously should be the same), hittest
function no longer work as espected and no longer return the object which is below the mouse. Below code illustrate the issue:
function [] = TestFigEvents()
%[
% Create figure
fig = figure(666);
clf(fig, 'reset');
fig.Color = 'black';
% Add axes
ax = axes();
daspect(ax, [1 1 1]);
ax.Visible = 'off';
ax.Clipping = 'off';
view(ax, -45, 30);
% Add something
s = surface(ax, 160*membrane(1,100));
s.EdgeColor = 'none';
% Different way to attach to mouse move event
if (true)
fig.WindowButtonMotionFcn = @onMouseMove;
else
addlistener(fig, 'WindowMouseMotion', @onMouseMove);
end
%]
end
function [] = onMouseMove(s, e)
%[
ht = hittest(s); % Will only detect correct object if using 'WindowButtonMotionFcn'
disp(ht);
%]
end
When going through WindowButtonMotionFcn
, the hittest
function indeed return the correct surface
object when the mouse is over it. But when going through WindowMouseMotion
event it is always returning the figure
object only.
Question
Well I guess nobody outside Mathworks staff can help me solving for undocumented hittest
not working when using events
instead of callbacks
, anyway:
- Is there another fast way I can detect objects below the mouse pointer rather than using
hittest
? - Is there a way I can attach to
WindowButtonMotionFcn
callback even if some callback is already defined for it ? - Maybe there already exist some sort of
uicad
toolbox that I could use to move/rotate object easily from the mouse (paying toolbox is ok) ?
edit
I tested both with R2022b and R2024b ... and also both with figure
and uifigure
... Here below is test code with uifigure
:
function [] = TestUiFigEvents()
%[
% Create figure
fig = uifigure();
fig.Color = 'black';
% Add axes
ax = uiaxes(fig);
daspect(ax, [1 1 1]);
ax.Visible = 'off';
ax.Clipping = 'off';
view(ax, -45, 30);
% Add something
s = surface(ax, 160*membrane(1,100));
s.EdgeColor = 'none';
% Different way to attach to mouse move event
if (false)
fig.WindowButtonMotionFcn = @onMouseMove;
else
addlistener(fig, 'WindowMouseMotion', @onMouseMove);
end
%]
end
function [] = onMouseMove(s, e)
%[
ht = hittest(e.Source); % Will only detect correct object if using 'WindowButtonMotionFcn'
disp(ht);
%]
end
Preamble
Some time ago, I created an application in matlab where I could move/rotate some object directly from the mouse (i.e. some kind of mini-cadtool interface):
I created the application on the go and was directly attaching to WindowButtonMotionFcn
callback in figure
properties and using the undocumented hittest
function to detect objects below the mouse and everything was fine ...
Now I would like to rework this code to extract cad-manipulation part to some sort of uicad
object just like we can have uicontrol
, uipanel
, etc... so I can use it as component on the shelf and plug it in any figure I want.
Especially I wanted not to directly modify WindowButtonMotionFcn
of the parent figure ... Indeed, if I want to do something modular, I cannot guarantee that this callback is not already in use (or will be in use) by someone else.
I then figured out that I could use equivalent WindowMouseMotion
event in figure
object so this way it is possible to attach as many event listeners as we want (see addlistener
) without disturbing other listeners or even disturbing the WindowButtonMotionFcn
property itself (which support only one listener).
Problem
Unfortunately when using event
instead of callback
(which obviously should be the same), hittest
function no longer work as espected and no longer return the object which is below the mouse. Below code illustrate the issue:
function [] = TestFigEvents()
%[
% Create figure
fig = figure(666);
clf(fig, 'reset');
fig.Color = 'black';
% Add axes
ax = axes();
daspect(ax, [1 1 1]);
ax.Visible = 'off';
ax.Clipping = 'off';
view(ax, -45, 30);
% Add something
s = surface(ax, 160*membrane(1,100));
s.EdgeColor = 'none';
% Different way to attach to mouse move event
if (true)
fig.WindowButtonMotionFcn = @onMouseMove;
else
addlistener(fig, 'WindowMouseMotion', @onMouseMove);
end
%]
end
function [] = onMouseMove(s, e)
%[
ht = hittest(s); % Will only detect correct object if using 'WindowButtonMotionFcn'
disp(ht);
%]
end
When going through WindowButtonMotionFcn
, the hittest
function indeed return the correct surface
object when the mouse is over it. But when going through WindowMouseMotion
event it is always returning the figure
object only.
Question
Well I guess nobody outside Mathworks staff can help me solving for undocumented hittest
not working when using events
instead of callbacks
, anyway:
- Is there another fast way I can detect objects below the mouse pointer rather than using
hittest
? - Is there a way I can attach to
WindowButtonMotionFcn
callback even if some callback is already defined for it ? - Maybe there already exist some sort of
uicad
toolbox that I could use to move/rotate object easily from the mouse (paying toolbox is ok) ?
edit
I tested both with R2022b and R2024b ... and also both with figure
and uifigure
... Here below is test code with uifigure
:
function [] = TestUiFigEvents()
%[
% Create figure
fig = uifigure();
fig.Color = 'black';
% Add axes
ax = uiaxes(fig);
daspect(ax, [1 1 1]);
ax.Visible = 'off';
ax.Clipping = 'off';
view(ax, -45, 30);
% Add something
s = surface(ax, 160*membrane(1,100));
s.EdgeColor = 'none';
% Different way to attach to mouse move event
if (false)
fig.WindowButtonMotionFcn = @onMouseMove;
else
addlistener(fig, 'WindowMouseMotion', @onMouseMove);
end
%]
end
function [] = onMouseMove(s, e)
%[
ht = hittest(e.Source); % Will only detect correct object if using 'WindowButtonMotionFcn'
disp(ht);
%]
end
Share
Improve this question
edited Mar 27 at 17:06
CitizenInsane
asked Mar 27 at 16:03
CitizenInsaneCitizenInsane
4,8752 gold badges29 silver badges61 bronze badges
4
|
1 Answer
Reset to default 0Suspicions I had that cascade of actions internally to matlab are likely as follow:
Mouse is moved > HitTest cache is reset > Event WindowMouseMotion is fired > HitTest cache is updated > WindowButtonMotionFcn callback is called
seems to be true, so I came out with following solution (here using UserData
to store user-defined callback if any + keeping debug messages, just for demo purpose):
function [] = TestFigEvents()
%[
...
% Attach as an event
addlistener(fig, 'WindowMouseMotion', @onMouseMove);
%]
end
function [] = onMouseMove(s, e)
%[
if (~iscell(s.UserData))
disp('Begin >> Event');
% Called by 'WindowMouseMotion' event
% So just temporarely replace 'WindowButtonMotionFcn'
s.UserData = { s.WindowButtonMotionFcn };
s.WindowButtonMotionFcn = @onMouseMove;
% Not clear why but does not work if not performing this 'drawnow'
drawnow;
disp('End << Event');
else
disp('Begin >> Callback');
% Called by 'WindowButtonMotionFcn' callback
% So do my stuff now that 'hittest' is ok
disp('Begin >> My own stuff');
ht = hittest(s);
disp(ht);
disp('End << My own stuff');
% Restore inal 'WindowButtonMotionFcn' an call it if not empty
s.WindowButtonMotionFcn = s.UserData{1};
s.UserData = [];
if (~isempty(s.WindowButtonMotionFcn)),
disp('Begin >> User defined stuff');
s.WindowButtonMotionFcn(s, e);
disp('end << User defined stuff');
end
disp('End << Callback');
end
%]
end
NB1: So far it is unclear why I need to call drawnow
but without it is not working (adding limitrate
option just decrease precision for hittest
detection, and nocallbacks
make it not to work).
NB2: Just doing a drawnow
in initial event-listener does not work:
function [] = onMouseMove(s, e)
%[
drawnow(); % This only does not make hittest to work
ht = hittest(s);
disp(ht);
%]
end
So I will go ahead with temporarely replacing WindowButtonMotionFcn
callback if any (+ quite strange but mandatory drawnow).
本文标签: matlabUndocumented hittest no longer working as expectedStack Overflow
版权声明:本文标题:matlab - Undocumented `hittest` no longer working as expected - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744081564a2587738.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
figure
anduifigure
(same issue in all cases). I edited question accordingly. – CitizenInsane Commented Mar 27 at 17:07WindowMouseMotion
is fired > HitTest cache is updated >WindowButtonMotionFcn
callback is called – CitizenInsane Commented Mar 27 at 17:25WindowButtonMotionFcn
inaddlistener
event listener and restore everything at the end of the call ... I will make more clean code for workaround i'm thinking of. – CitizenInsane Commented Mar 27 at 18:02