I have created a multiwindow GUI and have been confused with such a problem for a while:
I've got main GUI window with two buttons which are leading to two another GUI windows. One does not have an output_fcn options and closing normally, but another GUI window has 4 output arguments, which I use in subwindow and the problem is:
Attempt to reference field of non-structure array.
when i'm trying to close the window.
Here some code:
function varargout = changeme_dialog1_OutputFcn(hObject, eventdata, handles)
varargout{1} = get(handles.varP1,'String');
varargout{2} = get(handles.varP2,'String');
varargout{3} = get(handles.varP3,'String');
varargout{4} = get(handles.varP4,'String');
An error first appears in the varargout{1}.
What's the problem?
I ran into this problem several years ago, and am quite surprised if this turns out to be the same issue. The thing is, by the time OutputFcn is called, the handles structure was already deleted\cleared, for this reason you are getting an error because you're trying to reference something that MATLAB doesn't even recognize as a struct.
What I did was storing the outputs in appdata and retrieving them during OutputFcn (note: nothing's stopping you from retrieving the data in the calling code, but if you respect scope this is a more "correct" way to go about it IMO):
Step 1: Save outputs to appdata upon clicking a "close window" button:
function pushbutton1_Callback(hObject, eventdata, handles)
setappdata(0,'Output',{...
[handles.Hor1 handles.Ver1], [handles.Hor2 handles.Ver2]...
[handles.Hor3 handles.Ver3], [handles.Hor4 handles.Ver4]...
})
delete(handles.figure1); %// This actually initiates figure removal
(Here Hor1 ... Ver4 are just some example fields in handles.. In your case it would be get(handles.varP1,'String'); etc.)
Step 2: Retreive outputs from appdata, clearing it afterwards
function varargout = changeme_dialog1_OutputFcn(hObject, eventdata, handles)
...
varargout{1}=getappdata(0,'Output'); %// <== Wizardry Part 2
rmappdata(0,'Output') ;
...
I hope this helps or at least points you in the right direction.
Related
I have a problem in a Matlab GUI code. Let say for instance that I want to display in the console the value of a slider cursor in the GUI. But the fact is that I want to display it in real time, eg at each position of the cursor even if the click is still on, while moving it.
For this, I read on internet that the 'addlistener' function could help me. I put it in the slider_CreateFcn function like this :
function slider1_CreateFcn(hObject, eventdata, handles)
h=addlistener(hObject,'Value','PostSet',#(~,~)slider1_Callback)
Then, I added a simple disp function in the callback function, like this :
function slider1_Callback(hObject, eventdata, handles)
get(hObject,'value')
Running this code raise this error :
Warning: Error occurred while executing callback:
Error using get
Cannot find 'get' method for matlab.graphics.internal.GraphicsMetaProperty class.
Error in untitled>slider1_Callback (line xx)
get(hObject,'value')
If I remove the addlistener function, obviously the update is no more in real time, but I don't get the error message. So I think that the problem is directly coming from the addlistener function.
What is happening and how can I fix it?
First of all, the code that you posted isn't the code that is producing your error. I'm guessing that the code that yielded your error looked like this:
h = addlistener(hObject, 'Value', 'PostSet', #slider1_Callback);
In this instance, a meta property is passed as the first input argument to slider1_Callback which is giving you the immediate error you're seeing.
That being said, if you want to call slider1_Callback you need to craft an anonymous function which actually passes the correct type (and number) of inputs to the callback function. Here is one which does that.
function slider1_CreateFcn(hObject, eventdata, handles)
h = addlistener(hObject, 'Value', 'PostSet', ...
#(src,evnt)slider1_Callback(hObject, [], handles))
end
The better thing to do though, is to just use a separate callback rather then the one that GUIDE creates for you. This gives you a little bit more flexibility. Also, if you just want to display the value you don't need all of the other inputs and you can actually inline the entire callback rather than having a separate function.
h = addlistener(hObject, 'Value', 'PostSet', #(s,e)disp(get(hObject, 'Value')));
And to show it in action:
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 Matlab GUI that uses push button that executes certain code.
all of that works, except that when code reaches for loop, execution does not seem to enter that.
1) Any idea how for loop is implemented within framework of Matlab GUIDE code?
2) is there a way to debug GUI code ( only way I could was trough 'disp' statements,) using breakpoints, as when I run the GUI, breakpoints get removed.
after having read the solutions, I found that
(1) happened because the for loop index was not changing as length of array
that I was indexing on, was not changing. I explain this in the code.
(2) My bad, I was putting breakpoints before running the GUI, when I did the other way around, it breaks fine.
% Opening func
function Regression_OpeningFcn(hObject, ~, handles, varargin)
NoiseMin = -12;
NoiseMax = 10;
NoiseRes = 2;
handles.noiseMin = NoiseMin;
handles.noiseMax = NoiseMax;
handles.noiseRes = NoiseRes;
%**this executed when value changed in edit text box***
function noiseMinDbEditText_Callback(~, ~, handles)
handles.noiseMin = str2num(get(handles.noiseMinDbEditText,'String'));
% When GUI is running, following shows change from -12 sucessfully
disp(strcat('Noise Min = ',num2str(handles.noiseMin)));
function noiseMinDbEditText_CreateFcn(hObject, ~, ~)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor','white');
end
%Similar code for noiseMax and noiseRes(not shown here)
`% Here, code enters the Pushbutton callback
function StartRegressionPushButton_Callback(~, ~, handles)
snr_res = handles.noiseRes;
% here, snr_vecs still shows [-12 2 10]
snr_vecs = [handles.noiseMin:handles.noiseRes:handles.noiseMax];
So, basically, when GUI runs, entering and changing the values in text box corresponding to min, max and res snr variables shows me the change, but as soon as I enter the pushbutton dialog box, the changed values( that were captured in global variable "handles") do not show up as I break in the code there.
Any help with this? [for loop problem arose as I was indexing based on snr_vecs array, which is not changing, and so for loop was executing,but not as it should be]
sedy
Using Matlab guide
Guide is basically only a tool to create fig. files. All you can do with guide you could do yourself programmatically. Creating ui-elements works by hand just as easy as with guide (I actually prefere creating gui elements programmatically, since I think guide is very poorly coded)...
Every guide-elements has its callbacks which have to be coded somewhere, usually (I think 100% of the time) the fig file has the same name as the .m file. Find the corresponding .m-file and go to the callback you are interessted in. There you can place breakpoints just as easy as in any other piece of code.
Note: you can even change the code without having to reopen the fig file!
For loops or anything that works in regular code works for ui-element code.
The reason for handles not getting updated was missing following statement at end of function callback whose variable needs to be used in other callback.
guidata(hObject,handles);
I fixed that and it works nicely.
sedy
I developed a Matlab GUI program which it has four editbox & one pushbutton; my application works properly when I run it with Matlab software, but after converting it to exe file (standalone), the pushbutton doesn't work, means it doesn't show the output in 'Result' editbox. so what's the problem?
here is my pushbutton code:
function btnCal_Callback(hObject, eventdata, handles)
a=str2num(get(handles.txbLow,'string'));
b=str2num(get(handles.txbHi,'string'));
f=get(handles.txbForm,'string');
x=0.5*((b-a)*(-1*(3/5)^0.5)+b+a);
g=subs(f,'x',x);
sum=(g)*(5/9);
x=0.5*(b+a);
g=subs(f,'x',x);
sum=sum+(g)*(8/9);
x=.5*((b-a)*((3/5)^.5)+b+a);
g=subs(f,'x',x);
sum=sum+g*(5/9);
result=sum*((b-a)/2);
set(handles.txbResult,'string',result);
First, I'm a bit confused with
result=sum*((b-a)/2); % "result" is numeric
set(handles.txbResult,'string',result); % "result" should be string
Next, just as a hint. To "debug" your deployed code, try to launch your exe from cmd, in this case, you would see some messages there, and they might help.
your 'result' needs to be either double, char, or cell. You can do this by e.g.
set(handles.txbResult,'String',char(result);
However: I got exactly the same problem with a very similar code on my Mac. The Application runs very well if executed via "run" in Matlab, but once I compiled it to a standalone.app one hears this error-sound when pushing the button, nothing else is happening.
Trying to set the 'result' variable as "global" helped solving this problem for another program that I wrote (a very simple "calculate a+b" thing), but not for the mentioned slightly more complex code (3 instead of 2 inputs and 3 outputs instead of 1).
The super simple code which is working:
function pushbutton1_Callback(hObject, eventdata, handles) %the button to push
...some code...
global statText;
set(statText,'String',char(output));
function text1_CreateFcn(hObject, eventdata, handles) %the outputfield
global statText;
statText = hObject;
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.