Thursday, July 16, 2009

Topic #2 (Part2): Matlab GUI Callbacks

Last time we discussed the very basics of Matlab GUI. We learned what "handles" are and some of the primary functions that one would use to interact and gain additional functionality from a handle. In this section, I would like to discuss callback functions. Callback functions are a very important element to GUI programming. One of the key mindsets to GUI programming is to understand that they are "event-based" programs. Event based programs are programs that if left untouched do absolutely nothing, the only time when they execute functions is when the user interacts with it.

As we discussed last time there are some very fundamental functions that we must understand to use a graphical object. One of the is the "get" function. Say we create a window that contains a pushbutton by using the following code:

h=figure(1);
pb=uicontrol('Style', 'pushbutton');

Not much going on in the above statements. If we want to give the pushbutton some task to do, we would want to specify the callback function. To see all the attributes that can be set on the pushbutton, issue the command:

get(pb)

Which will return something like this:

BackgroundColor = [0.941176 0.941176 0.941176]
Callback =
CData = []
Enable = on
Extent = [0 0 4 4]
FontAngle = normal
FontName = MS Sans Serif
FontSize = [8]
FontUnits = points
FontWeight = normal
ForegroundColor = [0 0 0]
HorizontalAlignment = center
KeyPressFcn =
ListboxTop = [1]
Max = [1]
Min = [0]
Position = [20 20 60 20]
String =
Style = pushbutton
SliderStep = [0.01 0.1]
TooltipString =
Units = pixels
Value = [0]

BeingDeleted = off
ButtonDownFcn =
Children = []
Clipping = on
CreateFcn =
DeleteFcn =
BusyAction = queue
HandleVisibility = on
HitTest = on
Interruptible = on
Parent = [1]
Selected = off
SelectionHighlight = on
Tag =
Type = uicontrol
UIContextMenu = []
UserData = []
Visible = on

As you can see, "Callback" is not set to anything by default. Lets say we want it to compute x=sqrt(2) whenever we push the button. There are two ways we can set the callback.

Generally, the best way to handle a callback function is to make a function that does what you want the callback to do. In this case we would make and save a function like:

function rootTwo
sqrt(2)

And we would set the callback using:

set(pb,'Callback',rootTwo);

To make things even more trackable in your code you could make a single function that contains all the callback functions. For example, if you make a callback function called callbackFcn you could do this:

function callbackFcn(ID)
switch ID
case 1
disp('ID=1, pb1 pressed...')
sqrt(2)
otherwise
disp('Incorrect Callback ID...')
disp('Doing nothing.')
end

And you would set the Callback with the specific ID you want the function to be passed:

set(pb,'Callback',callbackFcn(1));

However, since this is such a simple task, instead of making another file that can make it difficult to navigate through your code, you may want to just emmbed that function into the callback string. This can be done using:

set(pb,'Callback','sqrt(2)');

Note: that if the function you are trying to use contains a string and you want to embed the function inout the callback string, then you need to use a second quotation for every single quote in the statement. For example, if I want to use the statement below in my callback:

x=['abc,'def'];

The I would have to use the "set" function like this:

set(pb,'Callback','x=[''abc,''def''];');

These second quotation marks act as a sort of "escape character" that prevents the callback function from being misinterpreted.

I think this is all I will discuss about callback functions for now. But be sure to use the "Product Help" in Matlab (search for uicontrol properties) to get more information.

But before I conclude this post I want to discuss two properties that are sort of overlooked by the average user. When you get more advanced in GUI design using Matlab, it isn't uncommon to have 100 handles that you need to interact with. Managing these handles can be a nightmare if you done understand some of the options that Matlab has set forth for such occassions. Two of the most useful properties that can be used are "Tag" and "UserData". The "Tag" is generally understood to be a unique name to that uicontrol. Say for instance you have three pushbuttons, it might be logical to give them Tag names: "pb1", "pb2", and "pb3". What this does is it gives the user a means to find a handle that a function does not have stored locally in its memory space. This is where the power of the function "findobj" comes in. Findobj takes in a couple arguments, the first is a property name and the second is the corresponding property value to look for. If I want to find the handle of the pushbutton with the Tag='pb2', I would issue the command:

findobj('Tag','pb2')

The second and more interesting property is the 'UserData' property. Matlab documentation says that this has no inherent function or purpose, so what we can do is exploit this and use it as a sort of heirarchy for graphical objects. Say you have several objects that you would like to operate on in the same exact manner. Instead of individually referencing their unique Tag names you can make a group name using UserData. If I want pb1, pb2, and pb3 to all get set to invisible it might be nice to group them first so that in the future the number of statements I have to code are reduced. Here is a full example of how one could use UserData:

uicontrol('Style','pushbutton',...
'Tag','pb1',...
'UserData','pbGroup');
uicontrol('Style','pushbutton',...
'Tag','pb2',...
'UserData','pbGroup');
uicontrol('Style','pushbutton',...
'Tag','pb3',...
'UserData','pbGroup');
handles=findobj('UserData','pbGroup');
for i=1:length(handles)
set(handles(i),'Visible','off');
end

This is a very primative example but it should get the point across that you can keep using Tags to individually reference a handle and you can use UserData to reference a collection of handles. You can even get fancy with the UserData and have a function that reads the UserData and checks to see if an object belongs to more than one grouping and operate on that object accordingly.

I think this is enough for now. Eventually, I will post a videoclip that will showcase some GUIs that I made that use the features I have outlined above.

No comments:

Post a Comment