Running handles from GUI using timer object

Hello,
I am a beginner to MATLAB, tried searching on the help docs and Google, but wasn't able to figure out why my timer object won't run a particular GUI handle. I generated the GUI using GUIDE. The problem I have, in brief is following: I can call my function 'rando' from a button callback, but it doesn't seem to work if I call it from a timer object.
If you could please help me with this, I'd appreciate it. Thanks in advance. Here's the code:
function varargout = trial(varargin)
% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @trial_OpeningFcn, ...
'gui_OutputFcn', @trial_OutputFcn, ...
'gui_LayoutFcn', [] , ...
'gui_Callback', []);
if nargin && ischar(varargin{1})
gui_State.gui_Callback = str2func(varargin{1});
end
if nargout
[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT
% --- Executes just before trial is made visible.
function trial_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% varargin command line arguments to trial (see VARARGIN)
% Choose default command line output for trial
handles.output = hObject;
% [X, map] = imread('C:\Users\Lemonickous\Documents\Courses\DC\DCseminar\images, etc\dc\untitled.jpg');
% image(X)
% colormap(map)
% axis off
handles.a = timer;
% Update handles structure
guidata(hObject, handles);
% UIWAIT makes trial wait for user response (see UIRESUME)
% uiwait(handles.figure1);
% --- Outputs from this function are returned to the command line.
function varargout = trial_OutputFcn(hObject, eventdata, handles)
% varargout cell array for returning output args (see VARARGOUT);
% hObject handle to figure
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Get default command line output from handles structure
varargout{1} = handles.output;
% --- Executes on button press in pushbutton2.
function pushbutton2_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton2 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
%trial2;
delete(handles.figure1);
% --- Executes on button press in generate.
function generate_Callback(hObject, eventdata, handles)
% hObject handle to generate (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
t2 = randi(10);
set(handles.a, 'ExecutionMode', 'fixedrate');
set(handles.a, 'Period', .1);
set(handles.a, 'TasksToExecute', t2);
set(handles.a, 'TimerFcn', 'rando(hObject, eventdata, handles)');
start(handles.a)
% --- Executes on button press in button2.
function button2_Callback(hObject, eventdata, handles)
% hObject handle to button2 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
rando(hObject, eventdata, handles);
function rando(hObject, eventdata, handles)
t = randi(3);
if t == 1
out = 200000;
elseif t == 2
out = 240000;
else
out = 280000;
end
set(handles.disp, 'String', num2str(out));

 Accepted Answer

Any callback coded as a string is executed within the context of the base workspace. The base workspace does not have a rando function defined in it, as rando is private to the file trial.m
You should instead pass a function handle.
Do it like this:
function generate_Callback(hObject, eventdata, handles)
% hObject handle to generate (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
t2 = randi(10);
set(handles.a, 'ExecutionMode', 'fixedrate');
set(handles.a, 'Period', .1);
set(handles.a, 'TasksToExecute', t2);
set(handles.a, 'TimerFcn', {@rando, hObject});
start(handles.a)
% --- Executes on button press in button2.
function button2_Callback(hObject, eventdata, handles)
% hObject handle to button2 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
rando(hObject);
function rando(hObject)
t = randi(3);
if t == 1
out = 200000;
elseif t == 2
out = 240000;
else
out = 280000;
end
handles = guidata(hObject);
set(handles.disp, 'String', num2str(out));

More Answers (1)

I'm trying to do something similar. This isn't an answer, but a question about your code and GUI. Are pushbutton2, generate, and button2 all different push buttons? What is the rando() function for? I'm trying to use a variable from a different m-file (presently trying it as a global) but don't understand how to tie it to the timer function, i.e. I want to update the GUI periodically without pressing a button.

7 Comments

Yes, all three of those are different push buttons.
randio is there as a helper function to generate a random value that is either 200000 or 240000 or 280000 .
randio could have had its logic coded differently; it could have been coded as
function rando(hObject)
out = 200000 + randi(3) * 400000;
handles = guidata(hObject);
set(handles.disp, 'String', num2str(out));
But that's not really important. It is just some work that needs to be done when "button2" is pressed or the timer goes off, that the user choose to encapsulate in to a function.
Jeff, often the way to transfer data is to use
handles.YourVariable = NewValue;
guidata(handles);
and then the callback in the timer could use something like
function timer_updateGUI(hObject)
handles = guidata(hObject);
CurrentValue = handles.YourVariable
set(handles.Gui_Item, 'string', num2str(Currentvalue));
Of course the routine that set the value could have updated the GUI directly, but sometimes you want that setting routine to "run free" and update the internal data structures and then when the timer goes off, update the GUI with whatever the newest version of the data is.
You would, for example, use this kind of system for updating charts or plots with real-time data, which might involve a variable number of fetches from the instrument, but with graph updates to happen (say) every 3 seconds.
Thanks again Walter...
Actually, I'm not too concerned about the other code running free. Would it be easier to update the GUI directly? That's how I originally wanted to proceed, but had no idea how to do so. So how is it done?
Assuming you are not using nested functions to share variables:
The second routine needs to be able to access the GUI objects. To do that you could pass the handles of specific GUI objects to it (use a structure if there are more than one); or you could pass the handle of any object in the GUI to the second routine (the figure number if it is handy, but anything in the same figure if that is handier); or you could code a routine in the first section of code that will return either of those on demand; or you could use handle object Tag fields to tag something in the GUI and then use findobj() in the second GUI to search for that tag.
Once you have the handle of anything in the first GUI, you can use guidata() against that handle to return the current versions of the handles structure. You can access the fields of that structure and set() those handles to whatever value you want.
This probably sounds complicated, but that is mostly because of the flexibility. The code in your second routine could be as simple as
results_handle = findobj(0,'type','text', 'tag', 'results');
set(results_handle, 'String', 'Maximum bearing capacity exceeded. Limit one partridge per tree')
Yeah, it does sound complicated, at least to me. You especially lost me when you mentioned 2 separate GUIs. I only have one which I'm calling from within my m-file that creates all the data I want to display and update.
I said "second routine" not "second GUI". "Second routine" corresponds to your "different m-file", the one that creates the data to be displayed.
You start the gui, and press a button on it, and that starts the second m-file running? If so then in order for the code in that second m-file to get data from the GUI or to update the GUI, it needs to be able to locate a handle in that GUI. You can either pass a handle in to the second m-file, or you can use findobj() in the second m-file to locate a graphics handle.
I was actually doing it the other way round, i.e. calling the GUI from the other routine, but could probably change and call my main file from the gui.
The order doesn't really matter. When you call the GUI it will probably create the figures and uicontrols and set up their callbacks -- and then, having done those, return control to the calling routine. The figure number of the GUI is often returned as part of that.
The only important bit about the order is the "obvious in retrospect": the handle you wish to update in the GUI must have been created before you try to update it.

Sign in to comment.

Categories

Find more on Creating, Deleting, and Querying Graphics Objects in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!