0

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 Answers1

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);
sco1
  • 12,154
  • 5
  • 26
  • 48