2017-01-02 77 views
2

我想製作一個簡單的程序,在按下運行按鈕時在循環中顯示遞增的數字,並通過在循環中按下其他按鈕來更改該值。我使用我發現的程序到目前爲止增加了數量並正確顯示,但我使用的變量顯然是彼此獨立的,所以無論何時將該值重置爲0,循環都會繼續之前留下的位置重置。Matlab - GUI - 通過在其他回調中修改變量來修改變量

% --- Executes on button press in stop. 
function stop_Callback(hObject, eventdata, handles) 
test = 0; 
set(handles.display, 'String', num2str(test)); 
guidata(hObject, handles); 

% --- Executes on button press in run. 
function run_Callback(hObject, eventdata, handles) 
test = 1; 
while test > 0 
    test = test + 1; 
    set(handles.display, 'String', num2str(test)); 
    guidata(hObject, handles); 
    pause(1); 
end 

任何想法如何使這項測試變量全球,如何初始化它,我應該把它放在文件中?

回答

1

是的,這是預期的行爲!變量test的範圍對每個函數都是局部的,所以您不能在一個函數中更改它,並期望更改後的值出現在另一個函數中。

這裏有幾個選項!例如,您可以使用handles結構傳遞「全局」變量。在代碼中,你將不得不修改它,像這樣:

% --- Executes on button press in stop. 
function stop_Callback(hObject, eventdata, handles) 
handles.test = 0; 
set(handles.display, 'String', num2str(handles.test)); 
guidata(hObject, handles); % Store the changed handles structure 

% --- Executes on button press in start. 
function run_Callback(hObject, eventdata, handles) 
handles.test = 1; 
while handles.test > 0 
    handles.test = handles.test + 1; 
    set(handles.display, 'String', num2str(handles.test)); 
    guidata(hObject, handles); % stores the changed handles structure 
    pause(1); 
    handles = guidata(hObject); % updates "handles" to see the change! 
end 

這是一個非常標準的方法,但它有一些缺點:這是超級容易不小心遺漏更新或檢索handles結構。此外,由於這兩個功能並行運行,它們容易受到競爭條件的影響。

第二種方法是使用global語句。它插入容易:

% --- Executes on button press in stop. 
function stop_Callback(hObject, eventdata, handles) 
global test; 
test = 0; 
set(handles.display, 'String', num2str(test)); 
guidata(hObject, handles); 

% --- Executes on button press in run. 
function run_Callback(hObject, eventdata, handles) 
global test; 
test = 1; 
while test > 0 
    test = test + 1; 
    set(handles.display, 'String', num2str(test)); 
    guidata(hObject, handles); 
    pause(1); 
end 

然而,這也帶有一些缺點:現在變量test是真正的全球化。它可以在其他腳本,函數或GUI中進行更改,因此您應該選擇比test更獨特的名稱,並且一般要小心。另外,如果(單例)GUI在不關閉的情況下重新啓動,GUI的可視狀態,handles結構的內容以及全局變量的內容可能會變得「不同步」。我被這兩次咬傷,所以我不再使用這種方法。

第三種方法包含變量test應始終鏈接到GUI文本字段的事實。因此它使用display字段中的字符串替代變量。從本質上講,這意味着使用getsetstr2doublenum2str很多:

% --- Executes on button press in stop. 
function stop_Callback(hObject, eventdata, handles) 
set(handles.display, 'String', num2str(0)); 
guidata(hObject, handles); 

% --- Executes on button press in start. 
function run_Callback(hObject, eventdata, handles) 
set(handles.display, 'String', num2str(1)); 
while str2double(get(handles.display, 'String')) > 0 
    set(handles.display, 'String', ... 
     num2str(str2double(get(handles.display, 'String')) + 1)); 
    guidata(hObject, handles); 
    pause(1); 
end 

這是冗長的,但它是我在這些情況下使用。這是最健壯的解決方案,尤其是在重新啓動(單例)GUI時不首先關閉它。

+0

第一種方法按預期工作!我之前在測試中使用過它,但我沒有意識到這一行「handles = guidata(hObject);%更新」句柄「以查看更改!」所以它不見了,所以它的行爲就像我的請求中的代碼。 謝謝! – user3548298

+0

關於第一種和第三種方法,最有效的是什麼?我試圖爲音頻製作一個實時處理程序,我需要小心這個問題 – user3548298

+0

我的直覺告訴我,兩種方法都非常高效 - 帶有'global'聲明的方法可能是最快的。在第一種和第三種方法之間,我猜第一種方法更快。但只有測試才能確定。實時音頻可能會非常棘手,您可能需要解決更先進的魔法。無論如何,祝你好運! –

0

您可以將變量聲明爲全局變量。這會做。

% --- Executes on button press in stop. 
function stop_Callback(hObject, eventdata, handles) 
global test; 
test = 0; 
set(handles.display, 'String', num2str(test)); 
guidata(hObject, handles); 

% --- Executes on button press in run. 
function run_Callback(hObject, eventdata, handles) 
global test; 
test = 1; 
while test > 0 
    test = test + 1; 
    set(handles.display, 'String', num2str(test)); 
    guidata(hObject, handles); 
    pause(1); 
end 
0

如果你的項目是小,適合單個M-文件,你可以很容易地通過使用nested functions解決這個問題。

如果您正在使用指南讓您的GUI,那麼你可以通過以下方式做到這一點最容易:(一定要保存副本首先從GUI編輯自動生成的M文件)

  1. 打開m文件
  2. 如果功能不與關鍵字end結束,然後將其添加到定義的所有功能,除了第一個函數(其名稱是M-文件)
  3. 把額外end在你的m文件的最底部

之後,您在頂層函數中定義的任何變量都可用於較低層的函數(嵌套的函數,也是回調函數)。標準的Matlab編輯器將在此顏色之後以不同的方式突出顯示變量,如果它們具有跨越許多功能的範圍