I'm trying to create a simple gui in matlab and have some problems. The main idea of this simplified program is that I have a slider, it determines the frequency of a sine wave. Two plots show the resulting signal. A high res in 44100 Hz, and a low res in 100 Hz. Another slider determines the length of the signal being plotted (also this measured in Hz). The original program has quite a few more sliders to add more frequencies, but since I didn't think it was important I tried to scale it back for this question. The resulting code is still quite large, sorry for that.
My problem is it doesn't always update, and I get error messages. I try to store everything in handles, since I think this is how you're supposed to do it. handles.lowresx contains the low res time scale, handles.highresx contains the high res time scale. A temporary lowresy and highresy is then created in the function calcandplot(handles). Every time the time interval slider is moved, the function recalcx(hObject, newhz, handles) is called from the slider movement callback and a new lowresx and lowresy is calculated. It is then stored in guidata(hObject,handles) (I would hope) and these are used to calculate new lowresy and highresy for plotting. It doesn't seem to be stored though.
I'm not sure how to save the data now when it is a nested function inside the callback function. Am I supposed to call guidata(hObject, handles) all the way up in the call stack, meaning I have to pass down hObject as an argument to every function? Or only in the most inner function? I've tried both and none really work. And is it enough to just calculate lowresy and highresy and plot them, if I don't need them later, or should I save them in handles too, to make everything work right?
Do I have to call guidata(handles) after calling set(handles.intervaltext, 'String', num2str(val)) or does it update itself?
And I have a question about handles. The way I understand it a copy is created and passed down every time a function is called. Does this pose some kind of restrictions on how big data structures you can save there for it to be efficient? If a copy is created for every gui component when some kind of event is called on it (mouseover, key pressed etc) I can certainly see how things can get sluggish. Any tips for how to handle this?
Error message:
Reference to non-existent field 'lowresx'.
Error in gui>calcandplot (line 85)
lowresy = wave(handles.lowresx, handles.freq1);
Error in gui>intervalslider_Callback (line 106)
calcandplot(handles);
Code:
function varargout = gui(varargin)
% GUI MATLAB code for gui.fig
% GUI, by itself, creates a new GUI or raises the existing
% singleton*.
%
% H = GUI returns the handle to a new GUI or the handle to
% the existing singleton*.
%
% GUI('CALLBACK',hObject,eventData,handles,...) calls the local
% function named CALLBACK in GUI.M with the given input arguments.
%
% GUI('Property','Value',...) creates a new GUI or raises the
% existing singleton*. Starting from the left, property value pairs are
% applied to the GUI before gui_OpeningFcn gets called. An
% unrecognized property name or invalid value makes property application
% stop. All inputs are passed to gui_OpeningFcn via varargin.
%
% *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one
% instance to run (singleton)".
%
% See also: GUIDE, GUIDATA, GUIHANDLES
% Edit the above text to modify the response to help gui
% Last Modified by GUIDE v2.5 12-Oct-2016 14:18:38
% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @gui_OpeningFcn, ...
'gui_OutputFcn', @gui_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 gui is made visible.
function gui_OpeningFcn(hObject, eventdata, handles, varargin)
handles.freq1 = 0;
handles.lowsr = 1000;
handles.sr = 44100;
handles.lenhz = 220;
recalcx(hObject, handles.lenhz, handles);
'recalculated'
% Choose default command line output for gui
handles.output = hObject;
% Update handles structure
guidata(hObject, handles);
% UIWAIT makes gui wait for user response (see UIRESUME)
% uiwait(handles.figure1);
% --- Outputs from this function are returned to the command line.
function varargout = gui_OutputFcn(hObject, eventdata, handles)
varargout{1} = handles.output;
% --- Executes on slider movement.
function slider1_Callback(hObject, eventdata, handles)
val = get(hObject,'Value');
handles.freq1 = val;
guidata(hObject, handles);
set(handles.text1, 'String', num2str(val));
calcandplot(handles);
% --- Executes during object creation, after setting all properties.
function slider1_CreateFcn(hObject, eventdata, handles)
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor',[.9 .9 .9]);
end
function calcandplot(handles)
lowresy = wave(handles.lowresx, handles.freq1);
highresy = wave(handles.highresx, handles.freq1);
axes(handles.axes1);
plot(handles.lowresx,lowresy, 'o');
axes(handles.axes2);
plot(handles.highresx,highresy, 'o');
function y = wave(x, freq1)
% x in sec
y = sin(x*freq1);
% --- Executes on slider movement.
function intervalslider_Callback(hObject, eventdata, handles)
val = get(hObject,'Value');
recalcx(hObject, val, handles);
strcat('val is now ', num2str(val))
strcat('handles.lenhz is now', num2str(handles.lenhz))
guidata(hObject, handles);
set(handles.intervaltext, 'String', num2str(val));
handles
calcandplot(handles);
% --- Executes during object creation, after setting all properties.
function intervalslider_CreateFcn(hObject, eventdata, handles)
if isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor',[.9 .9 .9]);
end
function recalcx(hObject, newhz, handles)
handles.lenhz = newhz;
handles.lowresx = (0:1/handles.lowsr:(2*pi)/handles.lenhz)';
handles.highresx = (0:1/handles.sr:(2*pi)/handles.lenhz)';
strcat('inside handles is', num2str(handles.lenhz))
guidata(hObject, handles);
strcat('inside handles again is', num2str(handles.lenhz))