2016-07-14 97 views
-1

我的程序在用户点击轴对象时运行一个函数。该函数使用光标的位置并将其进度显示为动画。我需要的是当用户点击一个新的位置时停止当前正在运行的函数调用,然后调用这个新位置的函数。如何等待在gui回调函数中终止运行函数?

我的代码是这样的(在我的原代码,我使用guidatahandles而不是全局变量):

function TestUI 
clc; clear variables; close all; 
figure; axis equal; hold on; 
xlim([0 100]); ylim([0 100]); 
set(gca, 'ButtonDownFcn', @AxisButtonDownFcn); 
global AnimateIsRunning 
AnimateIsRunning = false; 
end 

function AxisButtonDownFcn(ah, ~) 
C = get(gca,'CurrentPoint'); 
global xnow ynow AnimateIsRunning 
xnow = C(1, 1); ynow = C(1, 2); 
if AnimateIsRunning 
    % ---> I need to wait for termination of currently running Animate 
end; 
Animate(ah, xnow, ynow); 
end 

function Animate(ah, x, y) 
T = -pi:0.02:pi; r = 5; 
global xnow ynow AnimateIsRunning 
AnimateIsRunning = true; 
for t = T 
    if ~((xnow==x)&&(ynow==y)) 
     return; 
    end; 
    ph = plot(ah, x+r*cos(t), y+r*sin(t), '.'); 
    drawnow; 
    delete(ph) 
end 
AnimateIsRunning = false; 
end 

我的问题是,任何新的点击中断当前正在运行的功能,并保持先前​​的运行Animate在一个堆栈。它使前一个动画的最后一个绘图保持可见。更糟糕的是,堆栈的大小似乎为8,并且较新的中断将被存储在队列中!含义用户只能更新位置8次。要查看问题,您可以运行上面的代码示例并重复单击轴对象。

现在,我想检查Animate是否在AxisButtonDownFcn中运行,并等待终止(或强制终止它),然后用新参数调用Animate

+0

在完成之前是否要禁止任何新的点击? – Suever

+0

@Suever不,我想等待'Animate'完成它的工作,它会在下一次迭代中检查'xnow'和'ynow'并返回。 – saastn

回答

0

由于memyself回答other question,这是不可能的,终止当前正在运行的Animate[或等待其结束],因为这两个AxisButtonDownFcnAnimate被称为在同一个线程。因此,可用的选项有:

  1. 使用全局变量,这实现起来很简单,但增加了复杂性和相互依存关系。你可以找到一些棘手的解决方案herehere
  2. 多线程,女巫试图在单独的线程中运行处理部分和UI交互。它会更健壮(如果你有处理线程的经验),但需要更多的编码。这个here有详细的实现。

我的解决方案基于使用全局变量。这是真的很喜欢我已经联系到的解决方案,但他们两人都试图实现启动/停止按钮,而我需要停止当前进程,并开始在同一时间一个新问题:

function TestUI 
clc; clear variables; close all; 
figure; axis equal; hold on; 
xlim([0 100]); ylim([0 100]); 
set(gca, 'ButtonDownFcn', @AxisButtonDownFcn); 
global AnimateIsRunning 
AnimateIsRunning = false; 
end 

function AxisButtonDownFcn(ah, ~) 
C = get(gca,'CurrentPoint'); 
global xnow ynow AnimateIsRunning 
xnow = C(1, 1); ynow = C(1, 2); 
if ~AnimateIsRunning 
    Animate(ah); 
end; 
end 

function Animate(ah) 
T = -pi:0.02:pi; r = 5; 
global xnow ynow AnimateIsRunning 
AnimateIsRunning = true; 
x = -1; y = -1; 
while ~((x==xnow)&&(y==ynow)) 
    x = xnow; y = ynow; 
    for t = T 
     if ~((xnow==x)&&(ynow==y)) 
      break; 
     end; 
     if ishandle(ah) 
      ph = plot(ah, x+r*cos(t), y+r*sin(t), '.'); 
      drawnow; 
      if ishandle(ph) 
       delete(ph) 
      end 
     end 
    end 
end; 
AnimateIsRunning = false; 
end 

它只防止Animate被调用两次。如果它没有运行,它会调用Animate,否则,它只会通知当前运行的Animate有新的请求。