Returning data from uibutton callback

Hi,
I want to create a script that lets me add rows to a uitable with a ui buttom. My script mostly does what I want, except that it doesn't store the inputed values when I edit the table, nor does it return the eddited table back to memory to be used later. Is anyone able to point me in the right direction?
clc
Support = [0];
Type = {false};
t = table(Support,Type);
fig = uifigure;
uit = uitable(fig,"Data",t);
btn = uibutton(fig,"Text","Add Row","Position", [400 100 100 50],"ButtonPushedFcn",@(src,event) buttonCallback(t,fig));
uit.ColumnEditable = true;
function buttonCallback(t,fig)
Support = 0;
Type = {false};
addrow = table(Support,Type);
t = [t;addrow];
uit = uitable(fig,"Data",t);
uit.ColumnEditable = true;
btn = uibutton(fig,"Text","Add Row","Position", [400 100 100 50],"ButtonPushedFcn",@(src,event) buttonCallback(t,fig));
end
Error using matlab.internal.capability.Capability.require (line 94)
This functionality is not available on remote platforms.

Error in matlab.ui.internal.uifigureImpl (line 32)
Capability.require(Capability.WebWindow);

Error in uifigure (line 34)
window = matlab.ui.internal.uifigureImpl(varargin{:});

1 Comment

"Is anyone able to point me in the right direction?"
That is not how to write code for a GUI.
You are still writing linear code: first A executes, then B, then C, etc. until your script reaches the end.
But GUIs are fundamentally asynchronous code, and thinking in terms of linear code is a major hinderance to writing a GUI (i.e. you need to change how you think about code being executed). Note that in general GUI events will occur in no particular sequence. It takes a while to change how you think about code, but here are a few tips:
  • write functions (not scripts).
  • the GUI calls your functions (not a script calls a GUI)
  • in other words: callback functions are triggered by GUI events
  • share data properly within the GUI (i.e. avoid evil ASSIGNIN et al).
Take a look on FEX to find plenty of GUI examples which show how to perform basic actions (like reading a button status), they are often a good way to see how tasks should be achieved:

Sign in to comment.

Answers (1)

An easy way to make the callback update the value of t is to nest the callback function inside the main function (which requires using a function - rather than a script - for the main function). Nested functions can access and modify variables in the workspaces of functions that contain them.
For example, in the code below, the variable t is used in both the main_GUI function and the buttonCallback function (which is nested in main_GUI), which means the two functions' workspaces share the variable t. Therefore, when buttonCallback changes t, t is modified in both functions' workspaces (since they share the variable):
function main_GUI()
Support = 0;
Type = {false};
t = table(Support,Type);
fig = uifigure;
uit = uitable(fig,"Data",t);
btn = uibutton(fig,"Text","Add Row","Position", [400 100 100 50],"ButtonPushedFcn",@(src,event) buttonCallback());
uit.ColumnEditable = true;
function buttonCallback()
newSupport = 0;
newType = {false};
addrow = {newSupport,newType};
uit.Data = [uit.Data; addrow]; % add a row to the uitable
t = uit.Data; % update t
end
end

3 Comments

Thanks, that is close to the behavoiur I want, but I was suprised that the function it isn't passing 't' back then to memory when you call main_GUI().
the following doesn't seem to result in the updated table [t] in memory. when you call t = main_GUI().
the disp(t) functions shows that table is being updated each loop.
I can write the data to a file if I put Save("xxx") within the loop, but that isn't what I was going for, I wanted it passed back to memory. I am not sure if I need to put a save button in there to exit the 'buttoncallback' loop but when I tried to do that using the return function, that didn't seem to work.
function [t] = main_GUI()
Support = [0];
Type = {false};
t = table(Support,Type);
fig = uifigure;
uit = uitable(fig,"Data",t);
btn = uibutton(fig,"Text","Add Row","Position", [400 100 100 50],"ButtonPushedFcn",@(src,event) buttonCallback(t,fig));
uit.ColumnEditable = true;
function buttonCallback(t,fig)
newSupport = 0;
newType = {false};
addrow = {newSupport,newType};
uit.Data = [uit.Data; addrow]; % add a row to the uitable
t = uit.Data; % update t
disp(t)
end
end
Voss
Voss on 19 May 2024
Edited: Voss on 20 May 2024
When main_GUI runs, as soon as it is done doing what it does, which is to create the table and the button, it returns, so the value of t returned is the initial value.
If you want main_GUI to wait before returning so that the use can interact with the table and/or button, you'll need a uiwait or waitfor command. And you'll need to decide the condition(s) for returning, e.g., have another button that says "Done" or similar whose callback sets a flag letting the program know the user is ready for main_GUI to return.
@James Browne: you can use WAITFOR:
For example, at the end of your main GUI code:
waitfor(fig)
The function (and your data) then returns when the figure is deleted. This is a simple, efficient, and reliable approach to including an asynchronous GUI within some linear code.

Sign in to comment.

Categories

Find more on Develop Apps Using App Designer in Help Center and File Exchange

Products

Asked:

on 18 May 2024

Edited:

on 20 May 2024

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!