Managing Application State in UI Components
Callback functions define UI component behavior in MATLAB applications. When components have interdependencies, callbacks often require access to data defined in the main application function or need to exchange information with other callbacks. Since each calback operates in its own scope, explicit data sharing mechanisms become essential.
Storing Application Information
UI components contain valuable information in their properties. All components feature a UserData property that can store any MATLAB variable. While limited to a single variable, you can use structures or cell arrays to store multiple values. A common approach involves storing application data in the parent figure's UserData property for centralized access:
mainWindow = uifigure;
calendar = uidatepicker(mainWindow);
currentDate = datetime("today");
mainWindow.UserData = struct("CalendarComponent", calendar, "CurrentDate", currentDate);
For simpler applications, consider storing data as variables in the main function and passing them directly to callbacks.
Callback Data Access Techniques
Three primary methods enable data sharing between callbacks:
Accessing UserData Properties
This approach centralizes data storage. Components can access the parenet figure through the ancestor function:
parentFig = ancestor(component, "figure", "toplevel");
Word Cloud Implementation Using UserData
function wordCloudUsingUserData
fig = uifigure;
grid = uigridlayout(fig, [2,2]);
grid.RowHeight = {'1x', 30};
grid.ColumnWidth = {'1x', '2x'};
inputBox = uitextarea(grid);
inputBox.Layout.Row = 1;
inputBox.Layout.Column = 1;
actionBtn = uibutton(grid);
actionBtn.Layout.Row = 2;
actionBtn.Layout.Column = 1;
actionBtn.Text = "Generate Cloud";
displayPanel = uipanel(grid);
displayPanel.Layout.Row = [1 2];
displayPanel.Layout.Column = 2;
fig.UserData = struct("InputField", inputBox, "DisplayArea", displayPanel);
actionBtn.ButtonPushedFcn = @generateCloud;
end
function generateCloud(src, ~)
fig = ancestor(src, "figure", "toplevel");
appData = fig.UserData;
inputComp = appData.InputField;
panelComp = appData.DisplayArea;
content = inputComp.Value;
terms = {};
for idx = 1:length(content)
segmented = strsplit(content{idx});
terms = [terms segmented];
end
catData = categorical(terms);
wordcloud(panelComp, catData);
end
Passing Data via Callback Arguments
This method restricts callback access to specific data parameters:
function wordCloudWithInputArgs
fig = uifigure;
grid = uigridlayout(fig, [2,2]);
grid.RowHeight = {'1x', 30};
grid.ColumnWidth = {'1x', '2x'};
textInput = uitextarea(grid);
textInput.Layout.Row = 1;
textInput.Layout.Column = 1;
triggerBtn = uibutton(grid);
triggerBtn.Layout.Row = 2;
triggerBtn.Layout.Column = 1;
triggerBtn.Text = "Create Cloud";
outputPanel = uipanel(grid);
outputPanel.Layout.Row = [1 2];
outputPanel.Layout.Column = 2;
triggerBtn.ButtonPushedFcn = {@createCloud, textInput, outputPanel};
end
function createCloud(~, ~, txtComp, panelComp)
enteredText = txtComp.Value;
wordList = {};
for segment = 1:length(enteredText)
parsed = strsplit(enteredText{segment});
wordList = [wordList parsed];
end
categorySet = categorical(wordList);
wordcloud(panelComp, categorySet);
end
Nested Callback Functions
Nested functions inherit the parent function's workspace, enabling direct data access:
function nestedCloudCallback
mainFig = uifigure;
layoutGrid = uigridlayout(mainFig, [2,2]);
layoutGrid.RowHeight = {'1x', 30};
layoutGrid.ColumnWidth = {'1x', '2x'};
textEntry = uitextarea(layoutGrid);
textEntry.Layout.Row = 1;
textEntry.Layout.Column = 1;
executeBtn = uibutton(layoutGrid);
executeBtn.Layout.Row = 2;
executeBtn.Layout.Column = 1;
executeBtn.Text = "Generate";
resultPanel = uipanel(layoutGrid);
resultPanel.Layout.Row = [1 2];
resultPanel.Layout.Column = 2;
executeBtn.ButtonPushedFcn = @processInput;
function processInput(~, ~)
userInput = textEntry.Value;
vocabulary = {};
for lineNum = 1:length(userInput)
separated = strsplit(userInput{lineNum});
vocabulary = [vocabulary separated];
end
wordCategories = categorical(vocabulary);
wordcloud(resultPanel, wordCategories);
end
end