2017-01-16 6 views
1

Это аналогичная проблема, с которой сталкиваются многие другие, где guidata(hOjbect, handles), похоже, не обновляет значение. Я использую его со слушателем, и не знаю, как это сделать.Matlab guidata (hObject, handleles), не обновляющий флаг в пользовательском интерфейсе при вызове из прослушивателя

В моих gui_OpeningFcn у меня есть следующие строки:

addlistener(handles.s, 'name', 'PostSet', @(s,e)updatefilesave(hObject, [], handles)); 

Это устанавливает слушатель соответствующим образом, и это делает называть updatefilesave, когда имя изменено. Однако, внутри updatefilesave является следующий код:

handles.fileUnsaved = true; 
guidata(hObject, handles); 

Внутри функции обе линии работают. Когда я останавливаю точку на первой строке и шаге, fileUnsaved получает значение true. После того, как я перешагую вторую строку (пока все еще внутри функции updatefilesave), handles.fileUnsaved по-прежнему установлен в значение true.

Однако, когда я выхожу из функции, зеленая стрелка попадает на линию addlistener в функции gui_OpeningFcn. на этом уровне handles.fileUnsaved теперь возвращается к false.

Как получить ручки для обновления при использовании прослушивателя?

EDIT

То, что я пытаюсь сделать, это знать, когда поля ввода изменились, так что я могу предложить пользователю сохранить свою работу перед закрытием программы. Я проверяю флаг fileUnsaved в CloseRequestFcn, и если это правда, я спрашиваю пользователя, хотят ли они сохранить до выхода.

function namebox_Callback(hObject, eventdata, handles) 

newName = handles.namebox.String; 
if ~isempty(newName) 
    handles.s.name = newName; % (listener gets triggered here post set) 
end 

handles.namebox.String = handles.s.name; 

guidata(hObject, handles); % (namebox's local handles with fileUnsaved set to false gets put into hObject) 

Вот почему я не могу назвать handles = guidata(hObject) в CloseRequestFcn. Единственный способ остановить это - позвонить handles = guidata(hObject) в обратном вызове имени ящика, прежде чем позвонить guidata(hObject, handles). Но делать это повсюду будет победить точку в использовании слушателей. Я бы просто пошел и установил fileUnsaved в true в каждой функции обратного вызова (около 50 из них).

ответ

0

В общем случае, если вы хотите иметь функцию, которую вы вызываете из одного обратного вызова, чтобы изменить handles, а затем, чтобы эти изменения были доступны для вызывающей функции, вам необходимо не только сохранить структуру handles в вызываемом (чтобы они были доступны для других обратных вызовов), но вам необходимо повторно загрузить структуру handles в вызывающей функции, иначе вызывающая функция просто будет использовать ее собственную локальную (и немодифицированную) копию handles, поскольку она не имеет чтобы узнать, что он был изменен.

function main_callback(hObject, eventData, handles) 

    % Set the value to one thing 
    handles.value = false; 

    sub_callback(hObject, eventData, handles); 

    % Check that the value is STILL false 
    disp(handles.value) 

    % Load in the change so that handles gets updated 
    handles = guidata(hObject); 

end 

function sub_callback(hObject, eventData, handles) 
    handles.value = true; 

    % Save the value 
    guidata(hObject, handles); 
end 

Другой вариант, чтобы иметь свою другую функцию фактически возвращение модифицированного handles

function handles = sub_callback(hObject, eventData, handles) 
    handles.value = true; 

    guidata(hObject, value); 
end 

, а затем из вызывающей функции вы можете использовать выходной аргумент, чтобы перезаписать локальную handles переменными

handles = sub_callback(hObject, eventData, handles); 

Теперь на ваш конкретный вопрос относительно addlistener, поскольку обратный вызов выполняется в «асинхронном» смысле, на самом деле нет смысла возвращать значение.Однако я бы рекомендовал перезагрузить данные handles (как показано в первом примере), прежде чем снова использовать handles (где вы ожидаете его изменения), чтобы убедиться, что у вас самая современная версия.

+0

Это в основном означает, что мне нужно изменить строку addlistener, чтобы включить какой-то вызов 'handles = guidata (hObject)'. Есть ли способ вставить несколько вызовов функций в вход функции addlistener? например, '@ (s, e) updatefilesave (hObject, [], handle); handle = guidata (hObject)' – toshiomagic

+0

@toshiomagic № Как я сказал в последней части моего ответа, вы не можете вернуть значение из ' addlistener', и поскольку он выполняется асинхронно, добавление 'handles = guidata (hObject)' в ваш код * после того, как * вы назначили слушателя, не будет работать. Вы должны поместить 'handles = guidata (hObject)' в свой код в строке, прежде чем вы получите доступ к 'handles' и ожидаете, что он будет другим. – Suever

+0

Ну, черт побери. Это в основном побеждает цель слушателя. Если мне нужно перейти к каждой функции, в которой 's' изменяется и говорит' handles = guidata (hObject) ', я мог бы просто пойти в каждое место и сказать' handles.fileUnsaved = true'. – toshiomagic