2015-05-16 4 views
2

У меня есть структура, содержащая некоторые параметры отладки i.e: dbs = struct('db1', 0, 'db2', 1). И пользователь может добавить дополнительные параметры отладки в эту структуру (, db4 и т. Д.) Позже, а также изменить значение существующих полей db1, db2.matlab - GUIDE с входными аргументами - uimenu autoupdates его подменю

Я хочу создать графический интерфейс пользователя dbGUI с uimenu Debug options. dbGUI следует принимать dbs в качестве входного аргумента, поэтому я положил varargin мое OpeningFcn GUI, так что я могу назвать 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 «Параметры отладки» должны показать подменит, соответствующие с dbs-х поля. Я хочу: как автоматически обновлять подменю, когда пользователь изменяет структуру dbs вне внешнего интерфейса графического интерфейса (в окне команд Matlab)?

Как было предложено с помощью @marco wassmer ниже, структура dbs должна быть объявлена ​​как класс дескриптора, унаследованный от dynamicprops и с использованием addlistener. Проблема заключается в следующем: когда пользователь меняет dbs в окне команд, функция updateFoo не может получить дескрипторы dbGUI, поэтому не может обновить значение для дескрипторов, и, наконец, uimenu_CallbackFcn не сможет обновить новые поля и значения.

Примечание. Я пытаюсь использовать графический интерфейс программно, но я предпочитаю GUIDE, так как мне легче компоновать компоненты.

ответ

0

Я только что узнал, что это может быть много проще:

Я просто объявляю dbs как класс ручек. Затем в GUI's OpeningFcn назначьте поле dbs: handles.myvar = varargin{1};. Поскольку dbs теперь является классом дескрипторов, все, что я делаю с dbs вне GUI (например, в окне команд), также будет обновляться до ручек 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); 
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

  • Otehr way должен был бы сделать dbs в объект handle и добавить слушателя в 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 то есть, «ведет себя» сейчас почти как структуры, execpt, когда кто-то изменяет одно из свойств, событие 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

+0

спасибо за ваше предложение. Но я не только хочу изменить значение полей, но и добавить больше полей. Я нашел что-то полезное с 'dynamicprops', но не смог заставить его запустить ... – scmg

+0

@scmg Я изменил anwser, чтобы использовать класс' dynamicprops', спасибо за ввод, довольно интересный этому классу –

+0

еще раз спасибо, но, к сожалению , ваш пример кода для класса имеет так много мелких ошибок, и я, наконец, не знаю, что GUI не работает из-за ошибок в функциях GUI или ошибок в классе ... – scmg

Смежные вопросы