wait for gui to finish - matlab

As already asked more or less in this question: https://stackoverflow.com/questions/14397729/working-with-multiple-guis-in-matlab
I want to have the output parameers and wait for a gui to finish.
I now use waitfor, but the output is always only a single handle
handle = uiConfigureCalibration('uiMain', handles.figure1);
waitfor(handle);
display(handle);
The output function of uiConfigureCalibration however passes several parameters:
function varargout = uiConfigureCalibration_OutputFcn(hObject, eventdata, handles)
varargout{1} = handles.output;
if isfieldRecursive(handles, 'handles.files.calibration')
varargout{2} = handles.files.calibration;
varargout{3} = handles.calibration;
end
Any chance to get these parameters somehow in the calling function ?

You would have to do
[output,FilesCalibration,Calibration] = uiConfigureCalibration('uiMain', handles.figure1);
to grab additional outputs - you are only asking for one output in your function call, so you always get one output. However, this will fail if you output single parameter.
Since number of outputs is variable, I think it is better to return structure containing all outputs:
function output = uiConfigureCalibration_OutputFcn(hObject, eventdata, handles)
output.output = handles.output;
if isfieldRecursive(handles, 'handles.files.calibration')
output.files.calibration = handles.files.calibration;
output.calibration = handles.calibration;
end
Now function essentially returns a subset of handles structure, containing 1 or 3 fields depending on the structure of handles

Related

BytesAvailableFcn callback not receiving updated handles

I created an interface which automatically reads in data through the serial port, hence the reason I implemented the BytesAvailableFcn Callback
handles.fileID.BytesAvailableFcnMode = 'terminator';
handles.fileID.BytesAvailableFcn = {#streamData_fastTrak, handles};
The data that is read is displayed in a table chosen by the user (through use of radio buttons in the GUI). When an option is chosen a callback occurs to save the selected radio button to a variable which is saved in the handles struct. I have followed the program step for step and I am sure this callback does occur and that the variable is saved. However when the serial callback occurs the handles struct still has the old option value.
Here is the serial callback code:
function handles = streamData_fastTrak(hObject, eventdata, handles)
handles.num = handles.num + 1;
%receive data through serial
line = transpose(fscanf(handles.fileID, ' %f ' ));
table_data = get(handles.uitable1, 'data');
table_data_style = get(handles.uitable4, 'data');
display(handles.butt_state);
display(handles.num);
if(fix(line(1)) == 1 && strcmp(handles.butt_state, 'style_button'))
table_data_style(handles.select_Indices(1), 2:(length(line)+1)) = num2cell(line);
set(handles.uitable4, 'data', table_data_style);
display(handles.select_Indices);
elseif(fix(line(1)) > 1 && strcmp(handles.butt_state, 'stat_button'))
table_data(line(1)-1, 1:length(line)) = num2cell(line);
set(handles.uitable1, 'data', table_data);
if(line(1) == countStates(handles))
streamSensor_1_2_3(hObject, handles);
handles.time_step = handles.time_step + 1;
end
end
And the radio button callback:
function uipanel2_SelectionChangeFcn(hObject, eventdata, handles)
handles.butt_state = get(get(handles.uipanel2,'SelectedObject'), 'tag');
display(handles.butt_state);
guidata(hObject, handles);
The way I see it there are 2 ways to approach the problem:
The first way (I don't recommend this as much as the second one) is to pass the data you want updates to a string control and have it read back by your serial port function.
The other way that i recommend is to include a dummy button with a call back that calls
handles.fileID.BytesAvailableFcn = {#streamData_fastTrak, handles};
Again - this will update the new "handles" data to the callback function
For example
Assuming a dummy push button with tag PB1
function handles = streamData_fastTrak(hObject, eventdata, handles)
%% do stuff here
%% update handles data
PB1_Callback (handles.PB1,event,dat)
guidata(handles.PB1,handles) %% function ends
%% dummy button callback function%%
function PB1_Callback(hObject,event,handles)
handles.fileID.BytesAvailableFcn = {#streamData_fastTrak, handles};
guidata(hObject,handles) %% dummy button function ends
You can make the dummy button invisible by making the background color of the button same as that of the UI.
When you first declare your callback function for the ByteAvailableFcn in the line:
handles.fileID.BytesAvailableFcn = {#streamData_fastTrak, handles};
Matlab assign the function handle to the event and also pass the handles stucture at this point of time. This is now frozen into the private workspace of the callback. If you change the handles structure later on in your code (as you do when you try to attach the variable handles.butt_state), the callback doesn't know it, it still use the handles structure that was passed when you declared the callback.
There are several ways of getting this value correctly but I'll give 2 of them:
1) get the value from the radio button when needed
in your streamData_fastTrak callback function, query the button state directly from the uicontrol (instead of checking for a saved value)
handles.butt_state = get(get(handles.uipanel2,'SelectedObject'), 'tag');
This way you are sure to get the latest state of the radio button.
2) Store value in appdata
Every time the button state is changed, store the value somewhere, but you still have to query this value when your callback want to execute. A good place to save values are in the appdata (accessed using setappdata and getappdata).
So in your button callback:
function uipanel2_SelectionChangeFcn(hObject, eventdata, handles)
butt_state = get(get(handles.uipanel2,'SelectedObject'), 'tag');
setappdata(handles.uipanel2, 'butt_state' , butt_state );
display(butt_state);
And in your streamData_fastTrak callback:
function handles = streamData_fastTrak(hObject, eventdata, handles)
butt_state = getappdata(handles.uipanel2, 'butt_state' );
%// and the rest of your code ...

handles are getting deleted

I have 3 row-vectors, and would like to output them out of my GUI, if I close it.
First I tried it with global variables in the GUI, which i access and put them in the output function:
global horizontalFrames;
global verticalFrames;
global blackFrames;
varargout{1} = horizontalFrames;
varargout{2} = verticalFrames;
varargout{3} = blackFrames;
But, all values are ALREADY AT THIS POINT zero, even if i set them in the code.
Why are they set zero?
Then I tried it by the use of handles like this:
handles.horizontalFrames = horizontalFrames;
handles.verticalFrames = verticalFrames;
handles.blackFrames = blackFrames;
somewhere in the code (where the values are NOT all zero)
and then write this in the output function:
varargout{1} = handles.horizontalFrames
varargout{2} = handles.verticalFrames
varargout{3} = handles.blackFrames
the handles cant be found. It seems, like the handles are not accessible from the output function, or they are deleted. I'm desperate... where is my data, why can't I simply output it?
I found it out. I had to update my handles with
guidata(hObject, handles);
"somewhere in the code" again, means, immediately after adding my variables.
Greets, hope it helps someone.

Matlab: Timer encounters error on non-structure array

Trying to use Timer in GUI. While attempting in following code it is showing error.
function main_OpeningFcn(hObject, eventdata, handles, varargin)
handles.output = hObject;
handles.timer = timer(...
'ExecutionMode', 'fixedRate', ... % Run timer repeatedly
'Period', 1, ... % Initial period is 1 sec.
'TimerFcn', {#send_Callback,hObject});
guidata(hObject, handles);
function send_Callback(hObject, eventdata, handles)
comma = get(handles.Tx_send, 'String');%Tx_send is a text field
TxText = char(comma);
sf = rc4e2(TxText,key);%rc4e2 is an encryption
key = TxText;
DBC = char(sf);
disp(DBC);
fwrite(handles.serConn, DBC);%serConn is COM port
The error: Error while evaluating TimerFcn for timer 'timer-1'. Attempt to reference field of non-structure array.
Try changing your timerFcn to {'send_Callback',handles}.
In your version (as written in the original question), you have to write
'TimerFcn', {#send_Callback,handles});
The reason MATLAB is showing this error is because when it calls the Callback function, it automatically passes the timer handle as first argument and an empty event structure as second argument. The argument you provide by using the cell array is the third one. This means, your send_Callback is called with the argument list handles.timer,event,hObject (in this case, hObject is the window handle).
Then in the Callback function, you try to access handles.Tx_send, but since handles is the third argument and you provided just the window handle as the third argument, MATLAB will try to access handles.output.Tx_send, which does not exist.
Passing handles as described above should solve your problem because then the callback will have access to the handles object.

Matlab gui error

this is a part of my gui which executes when i click on the push button
//
//
//
%VERIFICATION
% --- Executes on button press in pushbutton9.
function pushbutton9_Callback(hObject, eventdata, handles)
% hObject handle to pushbutton9 (see GCBO)
DIR=handles.directory;
%angle=Angles(DIR);
area=nor_area(DIR);
%area=0.002;
%display(area)
Check=verify(area);
%display(Check);
if(Check==0)
%message = sprintf('nClick the OK button to continue');
msgbox('The signature belongs to the same person!!!');
else
msgbox('The signature is forged!!!');
end
//
//
//
and this is the verify function
//
//
//
function flag= verify(area)
%area=0.8969;
%take=area;
%display(take)
flag=0;
extract = xlsread('D:\Project\Image_processing\important\best.xlsx', 'CW4:CW17');
c=size(extract);
%display(c)
for k = 1:c
if (extract(k)==area)
display(extract(k));
flag=1;
end
end
%display(flag)
//
//
//
best.xlsx is the excel file from which I am retrieving the values and comparing with the value I get from the main gui function. The problem is even if I send the area value explicitly its not working. If I try running each function individually that is gui separately and verify separately it sets the flag correctly, but when I run it together it's not setting the flag properly.
Take another look at the following lines in the verify function:
c = size(extract);
for k = 1:c
I presume you really want
c = numel(extract);
because size returns a vector.

define anonymous function as 2 of 4 outputs of m file function

I have an m-file function with 4 outputs. I would like to define an anonymous function that has the same inputs, but only produces 2 of the four outputs. Is this possible?
AFAIK, you can't do this with just an inline anonymous function, because that Matlab syntax doesn't provide a way of capturing and indexing in to multiple outputs of a function in a single expression. But you can write a couple reusable helper functions that do so, and then define anonymous functions using them.
Let's say your four argout function is named "f4".
function varargout = f4(x)
%F4 Dummy function that returns 4 argouts holding identifying indexes
varargout = num2cell(1:4);
Here's a reusable helper function that remaps outputs of a function call.
function varargout = callandmap(fcn, ix, varargin)
%CALLANDMAP Call a function and rearrange its output arguments
tmp = cell(1,max(ix)); % Capture up to the last argout used
[tmp{:}] = fcn(varargin{:}); % Call the original function
varargout = tmp(ix); % Remap the outputs
Now you can make anonymous, argout-remapping functions like this. Here, g holds an anonymous function that takes the same inputs as your original function, but just returns 2 of its original 4 outputs.
>> g = #(varargin) callandmap(#f4, [2 4], varargin{:})
g =
#(varargin)callandmap(#f4,[2,4],varargin{:})
>> [a,b] = g('dummy') % gets argouts 2 and 4 from original f4() function
a =
2
b =
4
>>
Using varargin allows you to omit trailing arguments when the resulting function handle is called. If you know all argins will always be provided, you can use named argins for readability if you want.
You can get even fancier and do this with a closure.
function fcn = mapargout(fcnIn, ixArgout)
%MAPARGOUT Create wrapper function that selects or reorders argouts
%
% fcn = argoutselector(fcnIn, ixArgout)
%
% Wraps a given function handle in a function that rearranges its argouts.
% This uses closures so it may have performance impacts.
%
% FcnIn is a function handle to wrap.
%
% IxArgout is a list of indexes in to the original functions argout list
% that should be used as the outputs of the new function.
%
% Returns a function handle to a new function.
fcn = #extractor;
function varargout = extractor(varargin)
n = max(ixArgout);
tmp = cell(1,n);
% Call the wrapped function, capturing all the original argouts
[tmp{:}] = fcnIn(varargin{:});
% And then select the ones you want
varargout = tmp(ixArgout);
end
end
This results in simpler code for creating the anonymous function. And you could compose it with other function wrapper calls.
>> g = mapargout(#f4, [2 4])
g =
#mapargout/extractor
>> [a,b] = g('dummy')
a =
2
b =
4
>>
But closures can be tricky to work with in Matlab and may have performance implications. The callandmap approach is probably preferable unless you need the extra power.
If the two outputs are #1 and #2, everything is fine, and you don't have to worry about the other two outputs.
If the two outputs are any two others, you have two options
(1) Create a wrapper function with two outputs (note that in newer versions of Matlab you can replace the unused outputs dummy by ~.
function [out1,out2] = wrapperFunction(in1,in2,in3)
[dummy,out1,dummy,out2] = mainFunction(in1,in2,in3);
(2) Add another input variable that allows you to switch your function's behavior
function varargout = mainFunction(in1,in2,in3,outputSwitch)
%# make output switch optional
if nargin < 4 || isempty(outputSwitch)
outputSwitch = 0;
end
%# calculation here that creates out1-4
if outputSwitch
%# the special case where we only want outputs 2 and 4
varargout = {out2,out4};
else
%# return all four outputs
varargout = {out1,out2,out3,out4}
end
Then you can create the anonymous function as usual.