2016-07-14 24 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有新的請求。