Callback functions are at the heart of every GUI, as they link between the controls the user sees and the actual functions the GUI performs.
<note important>Please note: Although I strongly recommend to follow the ideas layed out below, th toolbox does not do that yet in all cases, whereas newer code parts try to follow this scheme.</note>
Basically, it is often very useful to have a set of few, generic callback routines that all follow a common naming scheme.
At least one callback routine for every uicontrol
element in your GUI will be useful (and is the minimum you will need to implement).
Callback functions should end with _Callback
to distinguish them from calls to (internal or external) further functions.
Besides that, they should tell what kind of uicontrol
element they are used for.
For the generic callback routines (for details, see below), this would give you a list of callback functions like that:
pushbutton_Callback
edit_Callback
popupmenu_Callback
togglebutton_Callback
Every Matlab™ callback function needs to take at least two input arguments: source
and event
. Whereas source
is the handle of the caller of the callback routine (and therefore often proves to be very useful), the event
argument is still rarely used within Matlab™, but rather for Matlab™-internal purposes.
To add an additional argument (namely, an action) to a callback function call, use something as the following syntax:
uicontrol('Tag','some_edit',... 'Style','edit',... 'FontUnit','Pixel','Fontsize',12,... 'HorizontalAlignment','Left',... 'Visible','on',... 'Units','pixels',... 'String','',... 'Position',[10 10 80 25],... 'Callback',{@edit_Callback,'something'}... );
The above code listing gives you an example of a (real-world) edit uicontrol. Here, we are particularly interested in the last line, the “Callback
” argument.
What you see here is the function name of the callback routine, here “edit_Callback
”, prefixed by an “@
” sign and followed by the additional argument, here “something
”. The whole callback function string has to be surrounded by curly brackets.
The actual callback would look something like that:
function edit_Callback(source,~,action) try % If action is empty, return if isempty(action) return; end switch action case 'something' % Do something useful here otherwise % fallback st = dbstack; trEPRmsg(... [st.name ' : unknown action "' action '"'],... 'warning'); return; end catch exception throw(exception); end end
Here, you see clearly that we make use of the first input argument, source
, but not of the second input argument, event
. Therefore, the second input argument gets replaced by the tilde ~
.1)
A few other general coding conventions are apparent from this example as well:
try
-catch
constructs to surround the complete function code.action
input argument.switch
-case
-otherwise
construct to deal with several actions.otherwise
branch within the case
statement that tells the user about the function name, the callback function name, and the input argument that is not understood. (Note here the use of dbstack
to get all this information generically.)
Please note: The exception handling is not complete in this example. As shown here, it would not be very useful. To give you a more complete (real-world) example of a catch
-branch that actually makes use of the infrastructure for error handling provided by the toolbox:
catch exception try msgStr = ['An exception occurred in ' ... exception.stack(1).name '.']; trEPRmsg(msgStr,'error'); catch exception2 exception = addCause(exception2, exception); disp(msgStr); end try trEPRgui_bugreportwindow(exception); catch exception3 % If even displaying the bug report window fails... exception = addCause(exception3, exception); throw(exception); end end
Here, you see once again a very defensive programming strategy. First, the function tries to add a status message to the GUI status, and if that fails, it adds another exception to the first one. Second, it tries to call the bug reporter from the toolbox, and if that fails as well, it will finally throw the exception, after adding an exception for not being able to open the bug reporter. In this final case, there is nothing left to do than throwing an exception.
More details about robust programming can be found at the respective page.