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.

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.

 

* 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