MATLAB Answers

0

Return output from the main function after a specific callback

Asked by Zoltán Csáti on 19 Mar 2016
Latest activity Commented on by Zoltán Csáti on 13 Oct 2018
I am building a GUI programatically. I created a main function which sets the GUI objects and their callback definitions. After a specific event occurred (right mouse click), I want to return the coordinates clicked so far, i.e. end the main function with the returned values ( P, in the pseudocode below).
function P = main
set GUI elements
set callback: myCallback
end
function myCallback(varargin)
handle the mouse click event:
if leftMouseButton
store the clicked coordinates in the UserData property
else
return stoppingSignal
end
end
The clicking detection works well, but how to end function main? One dirty way I thought of is to call the CloseRequestFcn and within that use assignin('base', 'P', P), but isn't there a better solution?

  0 Comments

Sign in to comment.

Tags

Products

1 Answer

Answer by Walter Roberson
on 20 Mar 2016
 Accepted Answer

The main function needs to uiwait() or waitfor() something. After the wait it should check to see if output has been saved for it in some known location, and if so should return that. If not, then it needs to return some output anyhow or to error() deliberately or let the caller error by not returning something. (It might be given the go ahead to continue by the user choosing to close the figure instead of taking the proper callback.)
The callback that wants to allow the main to go ahead should uiresume() or should force the satisfaction of the event that main is waiting for.
Before returning, main might choose to delete the gui, hide it, or whatever is appropriate -- it is not mandatory to destroy the GUI when the constructing function returns.

  3 Comments

Thanks for your advice. With it, I managed to solve it. Here is the code, perhaps it will be useful for others.
function P = test
% Initialize graphics objects
S.fig = figure('DeleteFcn','close(''all'')');
S.ax = axes('Parent', S.fig, 'HandleVisibility','callback', ...
'Units','normalized', 'XLim',[0 1], 'Interruptible', 'off', ...
'YLim',[0 1]);
% Set the callbacks
set(S.ax, 'ButtonDownFcn',{@mouseclick,S});
set(S.ax, 'UserData', struct('terminate',false, 'vertices', []));
uiwait();
userStructure = get(S.ax, 'UserData');
set(S.ax, 'ButtonDownFcn', '');
P = userStructure.vertices;
end
function mouseclick(varargin)
% Process the clicking event
S = varargin{3}; % get the structure
userStructure = get(S.ax, 'UserData');
buttonType = get(S.fig, 'SelectionType');
selectedPoint = get(S.ax, 'CurrentPoint');
x = selectedPoint(1,1);
y = selectedPoint(1,2);
switch buttonType
case 'normal' % left mouse button click
line(x,y, 'Marker','o');
% Update the coordinates
vertices = userStructure.vertices;
vertices = [vertices; [x y]];
userStructure.vertices = vertices;
set(S.ax, 'UserData', userStructure);
case 'extend' %
set(S.ax, 'UserData','');
userStructure.terminate = true;
set(S.ax, 'UserData', userStructure);
uiresume;
end
end
One question about the above code: Why did you choose to add a 'terminate' structure to the userStructure variable saved to UserData? I can see how it is initially set to be 'false', and then when the user does not left-click it is set to 'true', but I can't understand where that information is actually used.
Thank you for sharing this bit of code. It's been very helpful for something I'm working on.
You are right, the 'terminate' field of the structure is not used. The test function should check that field:
if userStructure.terminate
return P;
end

Sign in to comment.