datacursormode:当UpdateFcn需要时间返回时,虚假的MouseMotion事件处理

时间:2016-09-13 21:32:00

标签: matlab matlab-figure

我在Mac OS 10.11.6(El Capitan)的Matlab 8.1.0.604(R2013a)中使用DATACURSORMODE

在下面的简单示例中,数据光标仅在单击的新位置时移动,而不是仅在移动鼠标时移动。这正是我想要的行为。但是,在我的代码中,我得到了一个不同的行为:第一次单击后,只要鼠标移动,光标就会移动,直到我随后双击。我没有故意要求后一种行为,也不想要它。

关键区别似乎是我的UpdateFcn回调代码需要时间来完成(让我们假设它总是会:我的回调旨在执行相当复杂的操作,并且已经尽可能地进行矢量化和优化。这可以通过以下示例中的pause语句进行模拟,如果取消注释,可能会复制问题(可能需要根据平台/设置调整持续时间)。

datacursormode.m中,“未完成的功能”评论提到数据光标模式对象抛出了 MouseMotionButtonDown个事件。这显然不是完整的故事,因为默认情况下,单独对鼠标运动没有任何反应,但某些事情会发生,可能是由于延迟,使其成功。

所以我的问题是:这个光标移动鼠标移动 - 直到你双击一个已知的特征/模式,或者只是意外的“未定义的行为”作为延迟的副作用?在任何一种情况下,我怎么能(以编程方式)阻止它发生,假设我实际上无法加速回调代码?

function demo

fig = 1;
figure(fig), close, figure(fig)  % ensure virgin figure
image
h = datacursormode(fig);
datacursormode(fig, 'on')
set(h, 'UpdateFcn', @callback)

function txt = callback(cbo, event)
% pause(0.1) % uncomment this line (and/or lengthen the delay as necessary) to replicate the problem 
txt = evalc('cbo,event,disp(get(event))');

2 个答案:

答案 0 :(得分:1)

我实际上无法在Windows上的R2012a或R2016a上重现您的问题,但听起来就像您的系统一样,当您点击时,MATLAB无法捕获ButtonUp事件。处理MouseMotion事件的原因是因为按住鼠标按钮时应该能够拖动光标。

假设它确实是导致这种情况的UpdateFcn的慢响应,您可以通过触发异步操作中的慢速部分来解决此问题,然后在完成时触发另一个更新。我认为,最普遍的形式是使用timerStartDelay非常短appdata。在下面的示例中,我使用datacursormode来共享function demo fig = 1; figure(fig), close, figure(fig) % ensure virgin figure image h = datacursormode(fig); datacursormode(fig, 'on') set(h, 'UpdateFcn', @cursormodecallback) setappdata(fig, 'cursormode',h); setappdata(fig, 'timer',timer('StartDelay',0.001, 'TimerFcn',@timercallback)); setappdata(fig, 'lasttxt','Initial text'); function txt = cursormodecallback(cbo, event) txt = getappdata(1,'lasttxt'); % Display the most recently generated text in the tooltip t = getappdata(1,'timer'); if strcmp(get(t,'Running'),'off') % If we have already asked for an updated tooltip and haven't got one yet then don't ask for another one set(t, 'UserData',{cbo,event}); % Store the data needed by the slow callback to generate the tooltip start(t); % Ask the timer to generate new text end function timercallback(cbo, event) cursordata = get(cbo,'UserData'); [cbo,event] = cursordata{:}; pause(1) txt = evalc('cbo,event,disp(get(event))'); if ~isequal(txt,getappdata(1,'lasttxt')) setappdata(1,'lasttxt',txt); % Store the latest text updateDataCursors(getappdata(1,'cursormode')); % Update the cursor so the text is displayed end 对象和计时器之间的句柄,但您可以在特定实现中以多种不同方式处理此问题。

UPDATE [Tfs_xxx].[dbo].[WorkItemsAre] SET AreaID=@AreaID,IterationID=@IterationID WHERE ID=@WorkItemID
UPDATE [Tfs_xxx].[dbo].[WorkItemsLatest] SET AreaID=@AreaID,IterationID=@IterationID WHERE ID=@WorkItemID
UPDATE [Tfs_xxx].[dbo].[WorkItemsWere] SET AreaID=@AreaID,IterationID=@IterationID WHERE ID=@WorkItemID

答案 1 :(得分:0)

这是Will解决方案的编辑版本,效果很好。 StartDelay值很关键:< = 6ms无法解决鼠标移动问题。 7ms大部分时间都解决了这个问题,但偶尔会失误。 10ms似乎相当可靠地工作(除了第一次在给定的新Matlab会话中,当事情很慢醒来时)。典型的Matlab实现flakiness ......

<p:confirmDialog appendTo="@(body)"