Share data between UI callbacks - Alternative to “global”
Use of global variables in the code seem perfect and deterministic but it takes longer time until the situation gets chaotic with many variables declared in global scope, which can hold back/delay in debugging and increase the level of complexity. General rule in many programming languages is “global” is a bad coding practice.
Many GUI APPS contain interdependent controls, graphical objects. Since each callback to graphical objects has its own scope, one must share data explicitly that needs access to. Instead of declaring variables as “global”, here are alternative methods that can be used for sharing data within graphical object apps a cleaner and intuitive way.
Below are the two approaches where "global" can be avoided in GUI callbacks.
- Store data in object properties like “userdata”, “tag”:
UI graphical objects contain properties holding certain information of these objects. For example, one can get/set position of the graphical object by using its value.
The following code uses “userdata”, “tag” property to share information between slider and pushbutton UI components.
clc; clear all; close all;
handles.fig = figure('position',[600 400 300 300]);
function sld_callback(h,v)
slider_val = get(h,'value');
var1 = get(h,'max') - slider_val;
h.userdata = [slider_val,var1];
end
function btn_callback(h,v)
slider_h = findobj('tag','slider');
data = get(slider_h,'userdata');
display(['value from slider callback is ', num2str(data(2))])
end
handles.slider = uicontrol(handles.fig,'style','slider','units','norm','position',[0.25 0.65 0.5 0.15],'callback',@sld_callback,'tag','slider',...
'userdata',[0,1]);
handles.ptb = uicontrol(handles.fig,'style','pushbutton','string','difference','units','norm','position',[0.25 0.25 0.5 0.25],'callback',@btn_callback);
undock
When we move the slider, slider callback uses in a structure.
h.userdata = [slider_val,var1]; % stores slider_val, var1 as a matrix in userdata property of slider.
When push button is clicked, its callback uses below commands to retrieve the data:
slider_h = findobj('tag','slider'); % finds the slider component by using “tag” property
data = get(slider_h,'userdata'); % gets slider_val and var1 values using slider userdata property.
- Store as Application data – using setappdata/getappdata:
* setappdata/getappdata - undocumented functions
Setappdata is used to store data to an graphical object as
setappdata(handles.fig,'sliderval',0);
where,
1st argument is the object name.
2nd argument is variable name to the value.
3rd argument is the value.
getappdata is used to retrieve data from an graphical object as
getappdata(h_fig,'sliderval');
where,
1st argument is the object name.
2nd argument is variable name that we want to retrieve.
The following code shows the usage of setappdata/getappdata
clc; clear all; close all;
handles.fig = figure('position',[600 400 300 300]);
setappdata(handles.fig,'sliderval',0);
setappdata(handles.fig,'val_diff',1);
function sld_callback(h,v)
slider_val = get(h,'value');
h_fig = get(h,'parent');
val_diff = get(h,'max') - slider_val;
setappdata(h_fig,'sliderval',slider_val);
setappdata(h_fig,'val_diff',val_diff);
end
function btn_callback(h,v)
h_fig = get(h,'parent');
slider_val = getappdata(h_fig,'sliderval');
diff_val = getappdata(h_fig,'val_diff');
display(['[slider val,',' difference value]','=', '[',num2str(slider_val),',',num2str(diff_val),']'])
end
handles.slider = uicontrol(handles.fig,'style','slider','units','norm','position',[0.25 0.65 0.5 0.15],'callback',@sld_callback,'tag','slider');
handles.ptb = uicontrol(handles.fig,'style','pushbutton','string','Values','units','norm','position',[0.25 0.25 0.5 0.25],'callback',@btn_callback);
undock