从侦听器调用时,Matlab guidata(hObject,handles)未更新 UI 中的标志
Matlab guidata(hObject, handles) not updating flag in UI when called from listener
这是许多其他人遇到的类似问题,其中 guidata(hOjbect, handles)
似乎没有更新值。我正在将它与侦听器一起使用,但不确定如何进行。
在我的 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。
但是,当我退出该函数时,绿色箭头会出现在 gui_OpeningFcn
函数的 addlistener
行上。在此级别,handles.fileUnsaved
现在设置回 false。
如何在使用侦听器时获取要更新的句柄?
编辑
我想做的是知道输入字段何时更改,以便我可以提示用户在关闭程序之前保存他们的工作。我检查了 CloseRequestFcn 中的 fileUnsaved 标志,如果为真,我会在退出前询问用户是否要保存。
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)
这就是为什么我不能在 CloseRequestFcn
中调用 handles = guidata(hObject)
的原因。阻止这种情况的唯一方法是在我调用 guidata(hObject, handles)
之前在名称框回调中调用 handles = guidata(hObject)
。但是在任何地方都这样做会破坏使用听众的意义。我会在每个回调函数(大约 50 个)中将 fileUnsaved 设置为 true。
一般来说,如果您希望从一个回调中调用一个函数来修改 handles
,然后让调用函数可以使用这些更改,您不仅需要保存handles
被调用函数中的结构(以便它们可用于其他回调),但你必须 re-load 调用函数中的 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
另一种选择,是让你的其他功能实际上 return 修改后的 handles
function handles = sub_callback(hObject, eventData, handles)
handles.value = true;
guidata(hObject, value);
end
然后在调用函数中,您可以使用输出参数覆盖本地 handles
变量
handles = sub_callback(hObject, eventData, handles);
现在回答你关于 addlistener
的具体问题,因为回调是在 "asynchronous" 意义上执行的,return 一个值实际上没有意义。不过,我建议的是重新加载 handles
数据(如第一个示例所示),然后再次使用 handles
(您希望它被更改的地方)以确保您拥有大多数 up-to-date 版本。
我偶然发现这个线程也有类似的问题,但对我来说修改监听器内部的句柄似乎有效。
在外部函数中,我有这样的东西:
handles.myListener = addlistener(ObjectThrowingEvent,'EventName', @(src,evt)ListenerFunction(src, evnt, hObject));
guidata(hObject,handles);
然后在函数里面
function ListenerFunction(ObjectThrowingEvent, eventData, hObject)
handles = guidata(hObject)
% a bunch of stuff happens, including updates to the handles structure
guidata(hObject, handles);
对我来说,不同之处在于我传入 hObject 并在侦听器中查找来自 hObject 的句柄。即使侦听器是异步的,它也会被传递给 hObject,我认为它只是指向图形的当前状态,而不是一些本地未更新的副本。
我很好奇这是否适合您。到目前为止,它似乎在我的代码中有效。
这是许多其他人遇到的类似问题,其中 guidata(hOjbect, handles)
似乎没有更新值。我正在将它与侦听器一起使用,但不确定如何进行。
在我的 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。
但是,当我退出该函数时,绿色箭头会出现在 gui_OpeningFcn
函数的 addlistener
行上。在此级别,handles.fileUnsaved
现在设置回 false。
如何在使用侦听器时获取要更新的句柄?
编辑
我想做的是知道输入字段何时更改,以便我可以提示用户在关闭程序之前保存他们的工作。我检查了 CloseRequestFcn 中的 fileUnsaved 标志,如果为真,我会在退出前询问用户是否要保存。
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)
这就是为什么我不能在 CloseRequestFcn
中调用 handles = guidata(hObject)
的原因。阻止这种情况的唯一方法是在我调用 guidata(hObject, handles)
之前在名称框回调中调用 handles = guidata(hObject)
。但是在任何地方都这样做会破坏使用听众的意义。我会在每个回调函数(大约 50 个)中将 fileUnsaved 设置为 true。
一般来说,如果您希望从一个回调中调用一个函数来修改 handles
,然后让调用函数可以使用这些更改,您不仅需要保存handles
被调用函数中的结构(以便它们可用于其他回调),但你必须 re-load 调用函数中的 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
另一种选择,是让你的其他功能实际上 return 修改后的 handles
function handles = sub_callback(hObject, eventData, handles)
handles.value = true;
guidata(hObject, value);
end
然后在调用函数中,您可以使用输出参数覆盖本地 handles
变量
handles = sub_callback(hObject, eventData, handles);
现在回答你关于 addlistener
的具体问题,因为回调是在 "asynchronous" 意义上执行的,return 一个值实际上没有意义。不过,我建议的是重新加载 handles
数据(如第一个示例所示),然后再次使用 handles
(您希望它被更改的地方)以确保您拥有大多数 up-to-date 版本。
我偶然发现这个线程也有类似的问题,但对我来说修改监听器内部的句柄似乎有效。
在外部函数中,我有这样的东西:
handles.myListener = addlistener(ObjectThrowingEvent,'EventName', @(src,evt)ListenerFunction(src, evnt, hObject));
guidata(hObject,handles);
然后在函数里面
function ListenerFunction(ObjectThrowingEvent, eventData, hObject)
handles = guidata(hObject)
% a bunch of stuff happens, including updates to the handles structure
guidata(hObject, handles);
对我来说,不同之处在于我传入 hObject 并在侦听器中查找来自 hObject 的句柄。即使侦听器是异步的,它也会被传递给 hObject,我认为它只是指向图形的当前状态,而不是一些本地未更新的副本。
我很好奇这是否适合您。到目前为止,它似乎在我的代码中有效。