MATLAB GUI - Button Press returning error - matlab

I have a simple MATLAB GUI Code, find attached. All it does is when a button is pressed it runs a function.
However when I press this button twice, it is throwing an error
Undefined function 'GUI' for input arguments of type 'struct'.
Error in #(hObject,eventdata)GUI('pushbutton1_Callback',hObject,eventdata,guidata(hObject))
Error while evaluating uicontrol Callback
% --- 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)
set(handles.pushbutton1, 'enable','off');
output = randomFunction();
a = 1
while(1)
a = a+1
if a == 4
break;
end
end
set(handles.pushbutton1, 'enable','on');

The issue is that randomFunction must either change the current working directory or modify your PATH such that the GUI function (GUI.m) is no longer on the path and able to be found when you click the button the second time.
If you'd like to stop this behavior you have two options
The preferred option would be to modify randomFunction to not make this modification. A function should always the user's environment to the way that it was before being called. You can easily do this by using onCleanup within randomFunction
function randomFunction()
folder = pwd;
cleanup = onCleanup(#()cd(folder));
% Normal contents of randomFunction
end
The other option within randomFunction though is to never use cd. This is the best practice. You can use full file paths instead to access files
filename = fullfile(folder, 'image.png');
imread(filename)
If you can't modify randomFunction you can modify your callback to remember what the current directory was before calling the function and then change it back after randomFunction completes. I would actually recommend using onCleanup to do this to ensure that the directory is changed back even if randomFunction errors out
function pushbutton1_Callback(hObject, eventdata, handles)
set(handles.pushbutton1, 'enable', 'off');
% Make sure that when this function ends we change back to the current folder
folder = pwd;
cleanup = onCleanup(#()cd(folder));
output = randomFunction();
a = 1
while(1)
a = a+1
if a == 4
break;
end
end
set(handles.pushbutton1, 'enable','on');

Related

Matlab GUI programming: use data imported with uiimport

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');
%...%

MATLAB - passing new value of parameter from GUI into .m script

I want to make simple GUI for my script, where I can edit parameter values and running that script.
I've created example scipt and GUI with 2 buttons. I'cant put script code into GUI code, I will need to aply it on much larger script.
So, script code:
number = 10;
variable(1:10) = NaN;
for i = 1:10;
variable(i) = i * number;
end
figure
plot(variable)
Push button code, that is working fine. script is name of .m file, not function:
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)
evalin('base','script')
But I dont know what to type into edit button code If i want to change value of "number" in the script:
function edit1_Callback(hObject, eventdata, handles)
% hObject handle to edit1 (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Hints: get(hObject,'String') returns contents of edit1 as text
% str2double(get(hObject,'String')) returns contents of edit1 as a double
And last thing, sometimes when I try to plot more graphs, one figure overwrites GUI figure and I can see only buttons, but not whole GUI.
Thank you fot any help.
The hint given in the last piece of code is enough.
a = str2double(get(hObject,'String'));
This will save the input value as a double, in the callback function's stack.
In order to pass this value to the caller script's (base) stack, use assignin
assignin('base', 'number', a)

Matlab GUIDE - Running a script from a push button and using the workspace variables

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);

reset ui value in Matlab GUI before changing to new value

So far, just say that I have a GUI and list of uicontrol in it with 1 push button that start the computation process. In the push button, the callback function look like this :
% --- Executes on button press in mulai.
function mulai_Callback(hObject, eventdata, handles)
% hObject handle to mulai (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
%--give the program "Working" status
set(handles.status,'String','Working');
%--empty some edit text
set(handles.misklasifikasi,'String','');
set(handles.nilaiakurasi,'String','');
set(handles.nilaiwaktu,'String','');
%--Some computation process
%--Giving the result
set(handles.misklasifikasi,'String',misklasifikasi);
set(handles.nilaiakurasi,'String',sprintf('%g%% ',akurasi));
set(handles.nilaiwaktu,'String',sprintf('%g detik ',waktu));
%--give the program ready status
set(handles.status,'String','Ready');
but when I try it the program like just do the command after the computation process, did I missed something???
Thanks in advance...
Try to put a drawnow just before you start the computation. This will force MATLAB to flush the GUI event queue. You want to also place another call at the end of the callback function.

Making universal variables in MATLAB GUI

I'm kind of new to MATLAB and I'm doing some experiments for a school project.
What I want is a GUI with 3 buttons, when you press either of the first two, it adds up to one on a variable (one variable for each button), and when you press the third button, it does something with the variables from the first two buttons.
I used "guide" and dragged and dropped the buttons, and then I modified the functions.
But I realized that my variables only exist inside the function for the button, so if I initialize them they would restart everytime I press the button, and also there is no way for my third button to know the value of the first two.
Is there a way to make this variables always present? Or pass them from a function to another?
My code it's just the automatic code generated by "guide", with a v1 = v1+1; in the first button callback function and v2 = v2+1 in the second one, and disp(v1) disp(v2) in the third.
I hope you understand what I mean, I'm not a native english speaker so...
Anyway, thanks a lot, hope it's something easy to fix.
You have several options:
use global variables as nhowe suggested. But using global variables is not a good practice: see Top 10 MATLAB code practices that make me cry, or Wikipedia article
use setappdata / getappdata functions to store your variables (this is the simpler one)
learn how to use and properly update the handles structure that appears in each callback function for GUI controls created in GUIDE (this one is more complicated).
Here is an example of *.m file for case #3. Most of GUIDE-generated code was removed showing only things related to your variables. Basically, you have to update the handles structure in each callback function that does some changes to it with guidata(hObject, handles); line. After this all subsequent callbacks will see the updated handles structure.
function varargout = GUIProgramWithVariables(varargin)
% Here goes some comment from GUIDE
% Begin initialization code - DO NOT EDIT
% . . . actual code skipped
% End initialization code - DO NOT EDIT
% --- Executes just before GUIProgramWithVariables is made visible.
function GUIProgramWithVariables_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 GUIProgramWithVariables (see VARARGIN)
% Choose default command line output for GUIProgramWithVariables
handles.output = hObject;
% Here your code starts. It should be at the end of OpeningFcn
% Add your fields to handles structure
handles.C1 = 1;
handles.C2 = 2;
handles.C3 = 3;
% this updates modified handles structure
% so all subsequent call-backs will see the changes
guidata(hObject, handles);
% --- Executes on button press in Button1
function Button1_Callback(hObject, eventdata, handles)
% hObject handle to BrowseButton (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Here we do the magic with Button1
handles.C1 = handles.C1 + 1;
% this updates modified handles structure
% so all subsequent call-backs will see the changes
guidata(hObject, handles);
% --- Executes on button press in Button2
function Button1_Callback(hObject, eventdata, handles)
% hObject handle to BrowseButton (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Here we do the magic with Button2
handles.C2 = handles.C2 + 1;
% this updates modified handles structure
% so all subsequent call-backs will see the changes
guidata(hObject, handles);
% --- Executes on button press in Button3
function Button3_Callback(hObject, eventdata, handles)
% hObject handle to BrowseButton (see GCBO)
% eventdata reserved - to be defined in a future version of MATLAB
% handles structure with handles and user data (see GUIDATA)
% Here we do the magic with Button3
handles.C3 = handles.C1 + handles.C2;
% this updates modified handles structure
% so all subsequent call-backs will see the changes
guidata(hObject, handles);
The following is not the best practice for large complicated programs, but for something simple like what you're trying to do it sounds like global variables would be perfect. Say that X, Y, and Z are the variables you want to share between functions. Add the following at the beginning of every function that uses them, and they will all have access to the same values.
global X Y Z