Reputation: 3407
In Python and JS we have closures, which returns a function with some of the variables pre-defined. e.g.
def make_printer(msg):
def printer():
print msg
return printer
Here I have a callback function
function show(object, eventdata)
that is to be set to the callback of my GUI
func = @show;
set(gcf, 'WindowButtonMotionFcn', func);
However, I want to add some additional parameters to this show
function.
Currently I'm using global variables to do that. But I think it would be elegant if we have a 'closures function'.
Yes we do have anonymous function in Matlab. However it seems to me that it is too simple to support 60-line procedures.
Upvotes: 2
Views: 1150
Reputation: 3397
There was once a document floating about the internet by Sergey Simakov. It was very terse , not especially descriptive but covered the bases. This was in my experience the most authoritive text on matlab GUI's. I suspect it still is ...
You're solving two/three problems :
Closure Problem
Nested functions resolve this problem.
function iterator = count(initial)
% Initialize
if ~exist('initial','var')
counter = 0
else
counter = initial
end
function varargout = next() % [1]
% Increment
counter = counter + 1
varargout = {counter} % [1]
end
iterator = @next
end
Note(s) :
Usage
counter = count(4) % Instantiate
number = counter() % Assignment
number =
5
Closed Scope + State problem
No ugly braces, worrying about scope, cell arrays of strings. If you need access to something it's under SELF no more FINDOBJ, USERDATA, SET/GETAPPDATA, GLOBAL nonsense.
classdef Figure < handle
properties
parent@double
button@double
label@double
counter@function_handle
end
methods
function self = Figure(initial)
self.counter = count(initial) % [1]
self.parent = figure('Position',[200,200,300,100])
self.button = uicontrol('String','Push', 'Callback', @self.up, 'Style', 'pushbutton', 'Units', 'normalized', 'Position', [0.05, 0.05, 0.9, 0.4])
self.label = uicontrol('String', self.counter(), 'Style', 'text', 'Units', 'normalized', 'Position', [0.05, 0.55, 0.9, 0.4])
end
function up(self,comp,data)
set(self.label,'String',self.counter())
end
end
end
Note(s):
Usage :
f = Figure(4) % Instantiate
number = get(f.label,'String') % Assign
number =
5
You may prefer :
f.label.get('String') % Fails (f.label is double not handle, go figure)
h = handle(f.label) % Convert Double to handle
number = h.get('String') % Works
number =
5
Upvotes: 2
Reputation: 8459
Since it looks like my comment was helpful, I'll explain what I mean about the struct thing. I think the way you are calling the callback functions is slightly different, so this may not work so well).
If you have a bunch of different callback functions, and a bunch of variables you want to pass to them, it is annoying and difficult to have a big list of input arguments for each function. Instead, I do something like this:
First create a bunch of UI components , but don't specify their callback functions, e.g
radio1_handle=uicontrol(panel1_handle,'Style','radiobutton',...
'Min',0,'Max',1,'Value',0,'Units','normalized','Position',[.8 .8 .2 .25]);
once you have made all the components, create a struct of variables you will be using
vars=struct('varName1',var1,'varName2',var2);
then update the UI components to include the callback functions
set(radio1_handle,'Callback',{@radio1_callback,vars});
now create the actual functions
function radio1_callback(object,eventData,vars)
So it's nothing fancy, just a potentially neater way than using multiple arguments.
Upvotes: 1
Reputation: 3407
Inspired by this question and @David's comment, I came up with the solution. (Maybe this is @David's answer, but not explicitly explained. So let me extend his comment into an answer.)
There is actually a way to add extra parameters to callbacks.
Just add the parameters to the end of the parameter list
function show(object, eventdata, extra)
and set the callback like this:
func = @show;
set(gcf, 'WindowButtonMotionFcn', func);
Passing Additional Input Arguments
You can define the callback function to accept additional input arguments by adding them to the function definition:
function myCallback(src,eventdata,arg1,arg2)
When using additional arguments for the callback function, you must set the value of the property to a cell array (i.e., enclose the function handle and arguments in curly braces):
figure('WindowButtonDownFcn',{@myCallback,arg1,arg2})
Upvotes: 1