问题
I have a GUI in MATLAB which contains a timer. I want every time the timer is called to increment an index by one, and store it in the guidata. I would like functionality to go backwards if needed, so just using the TasksExecuted field would not work. My problem is that the index simply does not increment. This is the declaration of the timer
handles.index= 1 ;
handles.timer = timer(...
'ExecutionMode', 'fixedRate', ... % Run timer repeatedly
'Period', 1, ... % Initial period is 1 sec.
'TimerFcn', {@update_display,hObject,handles}); % Specify callback
And this is the relevant part of the function.
function update_display(hObject,eventdata,hfigure,handles)
tin = evalin('base','t_in');
curtime = tin.time(handles.index);
fprintf('%f',handles.index);
index = handles.index;
...
handles.index = index+1
guidata(handles.figure1,handles);
Debug statements say that the index will always be two at the end of the function. What am I doing wrong here?
Thank you.
回答1:
When providing an input variable to a callback function, the variable that is passed when you invoke the callback is that variable as it exists when the callback is defined. You can see this with a simple example:
function testcode
handles.mainwindow = figure();
handles.idx = 1;
handles.button1 = uicontrol('Style','pushbutton', 'String', 'Button1', ...
'Units','normalized', 'Position', [0.05 0.05 .30 .90], ...
'Callback', {@button, handles} ...
);
handles.button2 = uicontrol('Style','pushbutton', 'String', 'Button2', ...
'Units','normalized', 'Position', [0.35 0.05 .30 .90], ...
'Callback', {@button, handles} ...
);
handles.button3 = uicontrol('Style','pushbutton', 'String', 'Button3', ...
'Units','normalized', 'Position', [0.65 0.05 .30 .90], ...
'Callback', {@button, handles} ...
);
end
function button(hObj,~,handles)
fprintf('Initial idx: %u\n', handles.idx);
handles.idx = handles.idx + 1;
guidata(hObj, handles);
tmp = guidata(hObj);
fprintf('Stored idx: %u\n', tmp.idx);
end
Push each button and check out the displayed output.
To get around this, you can utilize guidata
in update_display
to get and store your handles
structure rather than passing it explicitly:
handles.index = 1;
handles.timer = timer( ...
'ExecutionMode', 'fixedRate', ... % Run timer repeatedly
'Period', 1, ... % Initial period is 1 sec.
'TimerFcn', {@update_display,hObject}); % Specify callback
guidata(handles.figure1, handles);
and
function update_display(hObject,eventdata,hfigure)
handles = guidata(hfigure);
guidata(handles.figure1, handles);
tin = evalin('base','t_in');
curtime = tin.time(handles.index);
fprintf('%f',handles.index);
index = handles.index;
% ... do things
handles.index = index+1
guidata(handles.figure1,handles);
If this is a GUIDE GUI, modifying the handles
structure can have unintended consequences. I'd recommend instead using setappdata and getappdata:
setappdata(hObject, 'index', 1); % Assuming hObject is your figure window
handles.timer = timer(...
'ExecutionMode', 'fixedRate', ... % Run timer repeatedly
'Period', 1, ... % Initial period is 1 sec.
'TimerFcn', {@update_display,hObject}); % Specify callback
and
function update_display(hObject,eventdata,hfigure)
index = getappdata(hfigure, 'index');
% ... do things
index = index + 1;
setappdata(hfigure, 'index', index);
来源:https://stackoverflow.com/questions/38772048/guidata-not-updating-properly