I am programming a simple GUI which has to do 2 tasks:
1- import a set of data for a txt file
2- make some computation with the previously imported data
Both tasks are performed pressing a button, one button for each task.
For the "Load data" button (task 1) I used the uiimport command in the Callback of that button (as explained here Matlab Calling 'Import Data' with GUI Button):
S = uiimport('-file');
The data are loaded as a "191384x3 double".
I also modified the function as follow, in order to have S available for the 2nd button:
function S = load_data_Callback(hObject, eventdata, handles)
Then I press the second button to perform the 2nd task. In the Callback of the 2nd button I wrote
function pushbutton2_Callback(hObject, eventdata, handles, S)
loaded_data = S; % to access the data in the non structured array
% Then I want to have 3 separate vectors out of the structure
v1 = loaded_data(:,1);
v2 = loaded_data(:,2);
v3 = loaded_data(:,3);
When I press the 2nd button I get an error message:
Not enough input arguments.
loaded_data = S;
Error in gui_mainfcn (line 95)
feval(varargin{:});
What am I missing?
You need to store the output from the first function somewhere, where the second function will be able to access it. This is typically done by storing it either in some ui object UserData property, or to store in some special data storage structure that is attached attached to figure objects, and is accessed with either the guidata function, or the getappdata and setappdata functions.
dat=guidata(hObj); gets the guidata from hObj parent figure
guidata(hObj,dat); sets the guidata of the parent figure of hObj to dat
Working with guide, the guidata structure is populated by default with a structure containing all the ui objects, named after their tag. Extra fields may be added as needed. The handle argument from callbacks contains guidata(hObj).
Three possible implementations:
1. With guidata
Store the loaded data with guidata
function load_data_Callback(hObject, eventdata, handles)
% Load the file and save the result in variable S%
% Then: %
handles.S=S;
guidata(hObject,S);
It will be automatically loaded back in the handles input variable
function pushbutton2_Callback(hObject, eventdata, handles)
assert(isfield(handles,S),'Load some data first!');
loaded_data=handles.S;
%...%
2. With Userdata property (up to R2014a)
Store the loaded data into some uiobject UserData, e.g. pushbutton2
function load_data_Callback(hObject, eventdata, handles)
% Load the file and save the result in variable S%
% Then: %
set(handles.pushbutton2,'UserData',S,'Enable','on'); %You could disable pushbutton2 by default, until some data has been loaded
Recover the data from the UserData property
function pushbutton2_Callback(hObject, eventdata, handles)
loaded_data=get(hObject,'UserData');
assert(~isempty(loaded_data),'Load some data first!');
%...%
3. With appdata functions
Store the loaded data with setappdata
function load_data_Callback(hObject, eventdata, handles)
% Load the file and save the result in variable S%
% Then: %
setappdata(hObject,'loaded_data',S);
Recover with getappdata:
function pushbutton2_Callback(hObject, eventdata, handles)
assert(isappdata(hObject,'loaded_data'),'Load some data first!');
loaded_data=getappdata(hObject,'loaded_data');
%...%
Related
I have a script which takes in a bunch of data and outputs a results matrix called "results".
I can get the push button to run the script, but "results" is nowhere to be found...
I have a second script which uses "results" to do further analysis, which I want the second push button in the GUI to trigger.
function pushbutton3_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton3 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
processFirstSet
processFirstSet is the first script, but it's not clear to me how to proceed from here
What comes back from your script will remain inside the GUI environment, so when the scripts ends, the pushbutton call will end and your return data "results" will be lost.
Either pass it on into the next function while staying inside the GUI and continue using the data right there (then later saving it for example) eg
function pushbutton3_Callback(hObject, eventdata, handles)
results = processFirstSet
processSecondSet(results)
%do something else
or export to the matlab workspace using assignin (eg)
function pushbutton3_Callback(hObject, eventdata, handles)
results = processFirstSet;
export_name = 'my_data';
assignin('base',export_name,results);
Here some basic hints, as I said in the comments.
Take your scrip, and turn it into a function by making a new file and using this format (replace the areas marked with your script). Save it with the same name firstStepFunction.m
function [results] = firstStepFunction(c)
a = 1; %your script here
b = 7; %your script here
results = a+b+c; %your script here
end
you can then run this function from the command line by typing firstStepFunction(2) and it will return 10 as ans into the workspace. (c) behind the function name is the function argument, if you don't need to be flexible with your function, you can leave that empty, which might be the case if you just copy past your script into the function outline.
If you now use that inside the gui pushbutton function, you need to assign the return value results (which in the example is 10) to a variable or it will get lost, for example:
results = firstStepFunction(2);
now you have results stored in a variable inside your pushbutton function. And now you can export it as above, so the whole example in this case (make sure you saved the firstStepFunction) would be
function pushbutton3_Callback(hObject, eventdata, handles)
results = firstStepFunction(2);
export_name 'my_data';
assignin('base',export_name,results);
I have a function that reads 2 files and assign them to 2 variables:
skelfile='data/name.asf'; %asf and amc files are associated,both needed for later stages
motfile='data/name.amc';
[skel,mot]=readMocap(skelfile,motfile);%the function that i need to use is the readMocap
the above code will give variables skel,mot as 1X1 structs with information both numeric and characters(contains numbers,cells,strings,aarays as struct fields).
the problem is how to use the function inside a Gui!!
i use a pusshbutton that load the 2 files and show at 2 static texts the filenames of both asf,amc files
asf,amc files are files that contain Motion Capture data for a human skeleton
where asf has informations about the skeleton and amc about a movement(frame sequence)
function pushbutton_Callback(hObject, eventdata, handles)
% hObject handle to load_MoCap (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
[filename, pathname] = uigetfile('*.asf', 'MoCap files');
% show name at the static texts
if isequal(filename,0)
set(handles.asf_filename, 'String', 'Please select an .asf file to continue')
else
set(handles.asf_filename, 'String', filename)
skelfile=filename;
[filename2, pathname2] = uigetfile('*.amc;*.c3d', 'MoCap files');
if isequal(filename2,0)
set(handles.amc_filename, 'String', 'Please select an .amc file to continue')
else
set(handles.amc_filename, 'String', filename2)
%the problem
============
%from here i want to run the function and have at a static text the text that
%have when i write skel in the command promt of matlab, or at least somehow
%evaluate tha skel and mot have been assigned as structs
motfile=filename;
[skel,mot]= readMocap(skelfile, motfile);
handles.skel=skel;
handles.mot=mot;
set(handles.skel_mot,'String',skel)
% skel_mot is the static text that refer above
%and i use as property type at the set command th 'string' but i don't think
%that is correct . skel variable is a 1x1 struct
end
end
guidata(hObject,handles);
I don't have anything else in my code than the default when you start a blank gui.
a)Do i have to add something (handles)at the opening function of the gui??i don't want something to start before load the files.
b)i want to use the information from the files as inputs for other function that will be called from the gui so how can i use them as inputs when i called the function inside the gui??as skel,mot or handles.skel,handles.mot??
Thank you in advance for any response.
A few things:
Yes, you need to define the fields in handles in the opening function of your GUI. You don't need any files to open, just give them empty string values or nan values as appropriate.
You need to use the guidata function to store data in handles between callback. More information here. That way you can use handles.whatever to access variables in other callbacks.
You say that skel and mot are structures. set(handles.skel_mot,'String',skel) needs skel to be a string.
Make sure any functions you call from the gui are in the path where the gui can find them.
I found a solution to my problem!
i wrote a script that does what i want.Open from a pushbutton a window to choose my files, then i call the function inside the script so i have the structs skel,mot assigned with the wanted informations. At the end , i use the handles as Molly suggested and also the command assignin for having the skel,mot at the workspace.
so:
function GUI_1_OpeningFcn(hObject, eventdata, handles, varargin)
%default comments
handles.skel=NaN;
handles.mot=NaN;
% Choose default command line output for GUI_1
handles.output = hObject;
% Update handles structure
guidata(hObject, handles);
============
more of the default Gui code
============
%pushbutton function
function load_MoCap_Callback(hObject, eventdata, handles)
% hObject handle to load_MoCap (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
%callint the script
nameofthescript;
%here skel and mot have been assigned so i put them to the handles
handles.skel=skel;
handles.mot=mot;
%with that i have them at the workspace for evaluation of what i want to do next
assignin ('base', 'skel', handles.skel);
assignin('base','mot',handles.mot);
guidata(hObject,handles);
from then i can use handles.skel and handles.mot for inputs in any other function that i want
I am quite new with the MATLAB gui and I wandered how we could allow an editbox value to be modified once the callback to the corresponding function had already been done (ie once the value is entered inside the editbox).
Indeed I would like to save (with a pushbutton) the LAST data entered in my editbox in case the user modifies it before saving, not the first value entered for the first time.
Thanks in advance,
CODE SAMPLE:
function Data_Callback(hObject, eventdata, handles)
data = get(handles.data,'String'); %import value from editbox
data = str2double (data);
handles.Data = data;
function Save_data_Callback(hObject, eventdata, handles)
save('DATA.mat','data'); %save it in .mat file
close; clear all; clc
The callback of the text-box is excecuted, if the users changes the text within the text-box. There seems to be just one thing missing in your save-fcn:
you have to get the value from the handles-structure:
function Save_data_Callback(hObject, eventdata, handles)
data=handles.data;
save('DATA.mat','data'); %save it in .mat file
%I would suggest to leave out the clear all and clc-commands...
Inside of one parent function, I have a callback function related to a button on a gui.
When the button is pressed, one of the things it does is define a variable (let's say X) that needs to be persistent so that later on, another sub function to the parent function can use X.
(i.e. callback functionA creates variable X.
later on, functionB requires variable X to be known, to know a specific path to take)
Is there any way to go about this?
I've read up on using handles to pass it to the second function, but I can't seem to figure out a way to do this.
Indirectly from Matlab guidata documentation:
in the first callback function:
function first_Callback(hObject, eventdata, handles)
% add some additional data as a new field called x
handles.x = 1;
% Save the change you made to the structure
guidata(hObject, handles)
in the second callback function simply use handles.x because handles is already passed as a parameter to the second callback, if they belong to the same parent figure.
function second_Callback(hObject, eventdata, handles)
% a will have the value 1
a = handles.x;
Note: Even though you are saving handles to hObject (which is the current object that has called the callback function), the handles structures is visible to other objects on the same figure. Saving handles structure to hObject and saving to the parent figure are virtually the same. Also you only need to use guidata if you make changes to the handles structure. If you only read the value of a handles member, you don't need to save it after that.
I've written a Matlab script that reads in data using a virtual COMM port in real-time. I've done a significant amount of signal processing in an mfile.
Next, I felt the need to have a compact GUI that displays the information as summary.
I only recently started digging and reading more of Matlab's built-in GUI tool, GUIDE. I've followed a few tutorials and am successfully able to get my graphs to display on my GUI after a button-press.
However, I want the GUI to update in real-time. My data vector is constantly updating (reading in data from the COMM port). I want the GUI to keep updating the graphs with the newer data, as opposed to relying on a button press for an update. Can someone please point me in the right direction for background updating?
Here is the relevant code currently for the GUI:
% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
global data
global time
% Time domain plot
axes(handles.timeDomainPlot);
cla;
plot (time, data);
EDIT Changed code:
% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
%Setting it to display something when it ends
% t = timer('TimerFcn', 'timerOn=false; disp(''Updating GUI!'')',...
t = timer(...
'TasksToExecute', 10, ... % Number of times to run the timer object
'Period', 3, ...
'TimerFcn', GUIUpdate());
%Starting the timer
start(t)
function GUIUpdate()
global data
global time
%Parameters below axes
global min
global max
% Time domain plot
axes(handles.timeDomainPlot);
cla;
plot (time, data);
%Other parameters:
set(handles.mean, 'String', mean);
set(handles.max, 'String', max);
The error that I get is:
??? Error using ==> GUI_Learning>GUIUpdate
Too many output arguments.
Error in ==>
#(hObject,eventdata)GUI_Learning('pushbutton1_Callback',hObject,eventdata,guidata(hObject))
??? Error while evaluating uicontrol Callback
Here is an example using a timer with a timerFcn callback. I made a simple GUI with 1 axes and 1 button.
In the opening function I initialize the plot and create the timer. In the start button callback I start the timer and start manipulating the data. The timer function callback the just updates the y-data of the line via its handle. Below are the relevant functions from the GUI's M-file (snipped init section and output fcn.
function testTimer_OpeningFcn(hObject, eventdata, handles, varargin)
global y x
x = 0:.1:3*pi; % Make up some data and plot
y = sin(x);
handles.plot = plot(handles.axes1,x,y);
handles.timer = timer('ExecutionMode','fixedRate',...
'Period', 0.5,...
'TimerFcn', {#GUIUpdate,handles});
handles.output = hObject;
guidata(hObject, handles);
% --- Executes on button press in startButton.
function startButton_Callback(hObject, eventdata, handles)
global y x
start(handles.timer)
for i =1:30
y = sin(x+i/10);
pause(1)
end
function GUIUpdate(obj,event,handles)
global y
set(handles.plot,'ydata',y);
You may want a Stop button to stop the timer depending on how your GUI is structured and were/how the data is updated.
Edit: Basic handles info some of this is pretty basic and you may already know it:
An individual handle to an object contains a bunch of properties that you can read with the get() function or set with the set() function. So for example maybe I wanted to change the text of the startButton for some reason in my GUI.
set(handles.startButton,'String','Something Other Than Start');
You may just want to set a break point in your code somewhere (maybe in a button press) and play around with the handles struct. Running get() commands on various objects to learn their properties.
Now the handles structure contains all of the ... umm... handles to your GUI's objects as well as any custom items that may be convenient for your to store there. Most GUI callbacks automatically get passed the handles struct so you have easy access to all parts of the GUI.
Ex. The 'startButton' callback was automatically passed handles. So I had easy access to the timer object via handles.timer.
Which brings me to sticking custom things into handles. In the opening function I added a new item to the handles structure handles.timer and handles.plot because I knew they would be useful in other callbacks (like button press and the timerFcn callback).
However, to store these things permanently you need to use the 'guidata' function. This function basically either stores the modified handles struct or retrieves a copy of handles depending on how you call it. So the following line in the opening function is storing the modified handles structure (added .timer and .plot) into the main GUI.
guidata(hObject,handles);
Basically any time you add something in handles you should have that line to make the change permanent.
Now the other method of calling it is:
handles = guidata(hObject); %hObject can be any handle who is a child of the main GUI.
This will retrieve the handles structure for the GUI.
And last handles.output = hObject is just the default output when you launch your GUI. IF you call your GUI via Matlab's command line like this h = myGUI; it should return the handle to your GUI.
You need to use a timer object. Set the callback to be the function that updates the plots.
Take a look at Making Graphs Responsive with Data Linking
and the linkdata command.
If the same variable appears in plots in multiple figures, you can
link any of the plots to the variable. You can use linked plots in
concert with Marking Up Graphs with Data Brushing, but also on their
own. Linking plots lets you
Make graphs respond to changes in variables in the base workspace or within a function
Make graphs respond when you change variables in the Variable Editor and Command Line
Modify variables through data brushing that affect different graphical representations of them at once
Create graphical "watch windows" for debugging purposes
Watch windows are useful if you program in the MATLAB language. For
example, when refining a data processing algorithm to step through
your code, you can see graphs respond to changes in variables as a
function executes statements.
I made a quick and dirty test seen below and I am not sure how this will work in a GUI verses a function but may do the trick.
Note 1: I had to add a break point in my subroutine where it modifies the global y to actually see the plot auto-update. You may need some combination of drawnow, pause, or a timer if data is getting changed rapidly.
function testLinking()
global x y
%Links failed if the global did not also exist in the base workspace
evalin('base','global x y');
x = 0:.1:3*pi; % Make up some data and plot
y = sin(x);
h = plot(x,y,'ydatasource','y','xdatasource','x');
linkdata on
testSub
function testSub()
%Test to see if a sub can make a linked global refresh
global x y
for i = 1:10
%This should automatically update the plot.
y = sin(x+i/10);
end
Edit: there may be ways around the use of globals depending on how your functions are structured ... but I don't have time to dig into it to much.
You can add a callback on the serial object that executes a plotting function. You must attach the callback to the 'BytesAvailableFcn' event on the object (see this for more details on the properties of the com object).
Essentially, when there are bytes available on the com port, you instruct matlab to run a specific function. In your case, it will be the function updating the GUI. If you need to process the incoming data first, then your callback function will first do the signal processing and then do the plotting commands.