matlab - 带输入参数的GUIDE - uimenu自动更新其子菜单

时间:2015-05-16 13:02:30

标签: matlab matlab-guide

我有一个包含一些调试选项的结构,即:dbs = struct('db1', 0, 'db2', 1)。用户可以稍后向此结构(db3db4等)添加更多调试选项,以及更改现有字段db1db2的值。

我想用uimenu dbGUI创建一个GUI Debug optionsdbGUI应该将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,因为我更容易布局组件。

2 个答案:

答案 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中,将字段分配给dbshandles.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);