Да, это ожидаемое поведение! Область переменной 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
поистине глобальный характер. Его также можно изменить в других сценариях, функциях или графических интерфейсах, поэтому вы должны выбрать более уникальное имя, чем test
, и быть осторожным в целом. Кроме того, когда (singleton) GUI перезапускается, не закрывая его сначала, визуальное состояние GUI, содержимое структуры handles
и содержимое глобальных переменных могут стать «не синхронизированными». Я был укушен этим дважды, поэтому я больше не использую этот метод.
Третий способ заключается в том, что переменная test
всегда должна быть связана с текстовым полем графического интерфейса. Поэтому он использует строку в поле display
вместо переменной. По сути это означает, что с помощью get
, set
, str2double
и num2str
много:
% --- 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
Это многословным, но это то, что я использую в этих случаях. Это наиболее надежное решение, особенно при перезапуске (singleton) GUI без его первого закрытия.
Первый способ работает так, как планировалось! Я на самом деле использовал его ранее в своих тестах, но я не знал об этой строке «handles = guidata (hObject);% обновляет« ручки », чтобы увидеть изменение!» поэтому он отсутствовал, и поэтому он вел себя как код в моем запросе. Спасибо! – user3548298
Что касается первого и третьего методов, что было бы наиболее эффективным? Я пытаюсь сделать программу обработки в реальном времени для звука, и мне нужно быть осторожным в этом – user3548298
. Моя кишка говорит, что ни один из методов не очень эффективен - метод с оператором 'global', вероятно, является самым быстрым. Между первым и третьим методом, я предполагаю, что первый метод выполняется быстрее. Но только тест может решить наверняка. Звук в реальном времени может быть сложным, и вам, возможно, придется решать более совершенную магию. В любом случае, удачи! –