-1

当用户单击轴对象时,我的程序会运行一个函数。此函数使用光标的位置并将其进度显示为动画。我需要的是在用户单击新位置时停止当前正在运行的函数调用,然后为这个新位置调用函数。

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

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使用新参数调用。

4

1 回答 1

0

正如我自己回答了另一个问题一样,不可能终止当前正在运行的Animate [或等待其终止],因为两者AxisButtonDownFcnAnimate在同一个线程中调用。所以可用的选项是:

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

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

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的有新请求。

于 2016-07-15T07:43:02.640 回答