我有一个包含一些调试选项的结构,即:dbs = struct('db1', 0, 'db2', 1)
。用户可以稍后向此结构(db3
,db4
等)添加更多调试选项,以及更改现有字段db1
,db2
的值。
我想用uimenu dbGUI
创建一个GUI Debug options
。 dbGUI
应该将dbs
作为输入参数,所以我将varargin
放到我的GUI的OpeningFcn中,这样我就可以从命令窗口调用GUI,如dbGUI(dbs)
:< / p>
function dbGUI_OpeningFcn(hObject, eventdata, handles, varargin)
handles.dbNames = fieldnames(varargin{1});
handles.dbVal = cellfun(@(i) varargin{1}.(i), handles.dbNames);
uimenu&#34;调试选项&#34;应显示与dbs
的字段对应的子菜单。我想要的是:当用户从GUI外部修改结构dbs
时,如何自动更新子菜单(在Matlab命令窗口中的意思)?
正如下面的@marco wassmer所建议的,结构dbs
应该被声明为继承自dynamicprops
并使用addlistener
的句柄类。问题是:当用户在命令窗口中更改dbs
时,函数updateFoo
无法获取dbGUI
的句柄,因此无法将值更新为句柄,最后uimenu_CallbackFcn无法更新新字段和值。
注意:我尝试以编程方式使用GUI,但我更喜欢GUIDE,因为我更容易布局组件。
答案 0 :(得分:1)
您有两种选择:
每次用户点击时都会更新菜单,如下所示:
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中添加监听器。也许比你想象的要复杂一点,但在这里。 不要担心它的结构与结构几乎相同...... 首先,您需要创建一个句柄对象,因此需要创建一个类:
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
,即&#39;表现为&#39;现在几乎就像一个struct,execpt,当某个人更改其中一个属性时,事件StateChange
将被触发。
在开场功能中,您需要做的就是将侦听器和回调添加到对象事件&#39; StateChange&#39;:
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
答案 1 :(得分:0)
我刚刚发现它可以更加简单:
我只是将dbs
声明为句柄类。然后在GUI的OpeningFcn中,将字段分配给dbs
:handles.myvar = varargin{1};
。由于dbs
现在是一个句柄类,所以我在GUI外部(即在命令窗口中)使用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);