matlab - 带输入参数的 GUIDE - uimenu 自动更新其子菜单
matlab - GUIDE with input arguments - uimenu autoupdates its submenus
我有一个包含一些调试选项的结构,即:dbs = struct('db1', 0, 'db2', 1)
。并且用户可以稍后向该结构添加更多调试选项(db3
、db4
等),以及更改现有字段的值 db1
、db2
.
我想用 uimenu Debug options
创建一个 GUI dbGUI
。 dbGUI
应该将 dbs
作为输入参数,所以我将 varargin
放到我的 GUI 的 OpeningFcn 中,这样我就可以从命令 window 调用 GUI,例如 dbGUI(dbs)
:
function dbGUI_OpeningFcn(hObject, eventdata, handles, varargin)
handles.dbNames = fieldnames(varargin{1});
handles.dbVal = cellfun(@(i) varargin{1}.(i), handles.dbNames);
uimenu "Debug options" 应显示与 dbs
的字段对应的子菜单。我想要的是:当用户从 GUI 外部修改结构 dbs
时如何自动更新子菜单(意味着在 Matlab 命令中 window)?
正如下面@marco wassmer 所建议的,结构 dbs
应该被声明为句柄 class 继承自 dynamicprops
并使用 addlistener
。问题是:当用户在命令Window中更改dbs
时,函数updateFoo
无法获取dbGUI
的句柄,因此无法更新句柄的值,最后uimenu_CallbackFcn 无法更新新字段和值。
注意:我尝试以编程方式使用 GUI,但我更喜欢 GUIDE,因为它更容易布置组件。
您有两个选择:
每次用户点击时更新菜单,像这样:
handles.dbs_menue = uimenu(f,'Label','Debug options','Callback','@foo')
.
.
.
function foo(hObj)
dbs=getVariable('base','dbs')
handles.dbO = fieldnames(dbs.dbOptions)
% and replace all menue items...
根据 matworks,这是 不 推荐的,
来源:http://ch.mathworks.com/help/matlab/ref/uimenu-properties.html#prop_Callback
其他方法是将 dbs 变成一个句柄对象并在 GUI 中添加一个侦听器。可能比您想象的要复杂一些,但就是这样。
别担心,它的工作方式几乎与结构相同......
首先,您需要制作一个句柄对象,因此需要制作一个 class:
classdef dbs_class < dynamicprops
properties (Access='private')
lhs=[];
end
events
StateChange
end
methods
function obj=dbs_class(a)
addlistener(obj,'PropertyAdded',@eventPRadd);
%addlistener(obj,'StateChange',@(varargin) disp('change'));
end
function eventPRadd(obj,evnt)
names=fieldnames(obj);
meta_p=obj.findprop(names{end});
meta_p.SetObservable=true;
obj.lhs.(names{end})=addlistener(obj,names{end},'PostSet',@(varargin) notify(obj,'StateChange'))
obj.(names{end})=0;
notify(obj,'StateChange')
end
function removeprop(obj,name)
meta_p=obj.findprop(name);
delete(meta_p)
delete(obj.lhs.(name))
notify(obj,'StateChange')
end
end
结束
然后制作其中之一:
dbs=dbs_class(1);
这个变量dbs
也就是'behaves'现在几乎就像一个结构体,当有人改变其中一个属性时执行,事件StateChange
将被触发。
在打开函数中,您需要做的就是将侦听器和回调添加到对象事件'StateChange':
function gui_test(dbs_in)
handles.fig=figure('Tag','fig');
addlistener(dbs_in,'something_changed',@updateFoo);
handles.dbO = fieldnames(dbs_in);
handles.dbmenu= uimenu('Label','Debug');
for n=1:numel(handles.dbO)
if dbs_in.(handles.dbO{n})==1
uimenu(handles.dbmenu,'Label',handles.dbO{n},'Callback',@(varargin) disp(['Debugg mode :' handles.dbO{n}]));
end
end
guidata(handles.fig, handles);
function updateFoo(src,~)
handles=guidata(findobj('Type','Figure','Tag','fig'))
handles.dbO = fieldnames(src);
delete(get(handles.dbmenu,'Children'))
for n=1:numel(handles.dbO)
if src.(handles.dbO{n})==1
uimenu(handles.dbmenu,'Label',handles.dbO{n},'Callback',['disp([''DebuggingMode :' handles.dbO(n) '])']);
end
end
guidata(handles.fig, handles);
来源:http://ch.mathworks.com/help/matlab/matlab_oop/learning-to-use-events-and-listeners.html
我刚刚发现它可以更简单:
我只是将 dbs
声明为句柄 class。然后在GUI的OpeningFcn中,给dbs
赋一个字段:handles.myvar = varargin{1};
。由于 dbs
现在是句柄 class,我在 GUI 之外(即在命令 Window 中)使用 dbs
所做的一切也将更新为 GUI 的句柄。
function dbGUI_OpeningFcn(hObject, eventdata, handles, varargin)
handles.var = varargin{1};
% other fields in handles
guidata(hObject, handles);
function db_menu_Callback(hObject, eventdata, handles)
disp('Updated variable: ');
disp(handles.var);
% here do whatever i want ....
guidata(hObject, handles);
我有一个包含一些调试选项的结构,即:dbs = struct('db1', 0, 'db2', 1)
。并且用户可以稍后向该结构添加更多调试选项(db3
、db4
等),以及更改现有字段的值 db1
、db2
.
我想用 uimenu Debug options
创建一个 GUI dbGUI
。 dbGUI
应该将 dbs
作为输入参数,所以我将 varargin
放到我的 GUI 的 OpeningFcn 中,这样我就可以从命令 window 调用 GUI,例如 dbGUI(dbs)
:
function dbGUI_OpeningFcn(hObject, eventdata, handles, varargin)
handles.dbNames = fieldnames(varargin{1});
handles.dbVal = cellfun(@(i) varargin{1}.(i), handles.dbNames);
uimenu "Debug options" 应显示与 dbs
的字段对应的子菜单。我想要的是:当用户从 GUI 外部修改结构 dbs
时如何自动更新子菜单(意味着在 Matlab 命令中 window)?
正如下面@marco wassmer 所建议的,结构 dbs
应该被声明为句柄 class 继承自 dynamicprops
并使用 addlistener
。问题是:当用户在命令Window中更改dbs
时,函数updateFoo
无法获取dbGUI
的句柄,因此无法更新句柄的值,最后uimenu_CallbackFcn 无法更新新字段和值。
注意:我尝试以编程方式使用 GUI,但我更喜欢 GUIDE,因为它更容易布置组件。
您有两个选择:
每次用户点击时更新菜单,像这样:
handles.dbs_menue = uimenu(f,'Label','Debug options','Callback','@foo') . . . function foo(hObj) dbs=getVariable('base','dbs') handles.dbO = fieldnames(dbs.dbOptions) % and replace all menue items...
根据 matworks,这是 不 推荐的, 来源:http://ch.mathworks.com/help/matlab/ref/uimenu-properties.html#prop_Callback
其他方法是将 dbs 变成一个句柄对象并在 GUI 中添加一个侦听器。可能比您想象的要复杂一些,但就是这样。 别担心,它的工作方式几乎与结构相同...... 首先,您需要制作一个句柄对象,因此需要制作一个 class:
classdef dbs_class < dynamicprops properties (Access='private') lhs=[]; end events StateChange end methods function obj=dbs_class(a) addlistener(obj,'PropertyAdded',@eventPRadd); %addlistener(obj,'StateChange',@(varargin) disp('change')); end function eventPRadd(obj,evnt) names=fieldnames(obj); meta_p=obj.findprop(names{end}); meta_p.SetObservable=true; obj.lhs.(names{end})=addlistener(obj,names{end},'PostSet',@(varargin) notify(obj,'StateChange')) obj.(names{end})=0; notify(obj,'StateChange') end function removeprop(obj,name) meta_p=obj.findprop(name); delete(meta_p) delete(obj.lhs.(name)) notify(obj,'StateChange') end end
结束
然后制作其中之一:
dbs=dbs_class(1);
这个变量dbs
也就是'behaves'现在几乎就像一个结构体,当有人改变其中一个属性时执行,事件StateChange
将被触发。
在打开函数中,您需要做的就是将侦听器和回调添加到对象事件'StateChange':
function gui_test(dbs_in)
handles.fig=figure('Tag','fig');
addlistener(dbs_in,'something_changed',@updateFoo);
handles.dbO = fieldnames(dbs_in);
handles.dbmenu= uimenu('Label','Debug');
for n=1:numel(handles.dbO)
if dbs_in.(handles.dbO{n})==1
uimenu(handles.dbmenu,'Label',handles.dbO{n},'Callback',@(varargin) disp(['Debugg mode :' handles.dbO{n}]));
end
end
guidata(handles.fig, handles);
function updateFoo(src,~)
handles=guidata(findobj('Type','Figure','Tag','fig'))
handles.dbO = fieldnames(src);
delete(get(handles.dbmenu,'Children'))
for n=1:numel(handles.dbO)
if src.(handles.dbO{n})==1
uimenu(handles.dbmenu,'Label',handles.dbO{n},'Callback',['disp([''DebuggingMode :' handles.dbO(n) '])']);
end
end
guidata(handles.fig, handles);
来源:http://ch.mathworks.com/help/matlab/matlab_oop/learning-to-use-events-and-listeners.html
我刚刚发现它可以更简单:
我只是将 dbs
声明为句柄 class。然后在GUI的OpeningFcn中,给dbs
赋一个字段:handles.myvar = varargin{1};
。由于 dbs
现在是句柄 class,我在 GUI 之外(即在命令 Window 中)使用 dbs
所做的一切也将更新为 GUI 的句柄。
function dbGUI_OpeningFcn(hObject, eventdata, handles, varargin)
handles.var = varargin{1};
% other fields in handles
guidata(hObject, handles);
function db_menu_Callback(hObject, eventdata, handles)
disp('Updated variable: ');
disp(handles.var);
% here do whatever i want ....
guidata(hObject, handles);