如何等待 gui 回调函数中的 运行 函数终止?

How to wait for termination of a running function in a gui callback function?

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

我的代码是这样的(在我原来的代码中我使用 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

我的问题是,任何较新的点击都会中断当前 运行ning 功能,并将之前的 运行ning Animate 保留在堆栈中。它使上一个动画的最后一张图保持可见。更糟糕的是 stack 的大小似乎是 8,较新的中断将存储在 queue 中!这意味着用户只能更新位置 8 次。要查看问题,您可以 运行 上面的代码示例并重复单击坐标区对象。

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

作为memyself answered the other question,目前无法终止运行宁Animate[或等待其终止],因为两者AxisButtonDownFcnAnimate 在同一线程中调用。所以可用的选项是:

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

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

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被调用两次。如果不是运行ning,则调用Animate,否则,它只通知当前运行ning Animate有新请求。