Function not returning updated struct
5 views (last 30 days)
Show older comments
Simon Aldworth
on 30 Jun 2025
Commented: Simon Aldworth
on 3 Jul 2025
Hello,
My code passes a struct to a function that builds a gui to allow the user to modify the default values of variables stored in the struct. The struct should then be passed back to the main code. This last stage is not working correctly - the struct in the main code retains the original values. I've tested the code by writing a simpler version without the gui and this seems to work OK. The simple version is:
clear
clc
X.a = 1
X.b = 2
X_out = testfunc(X)
X_out.a
X_out.b
function X_new=testfunc(X_in)
X_new = X_in
X_new.a = 3
X_new.b = 5
ok_fun
function ok_fun
X_new.a = 7
X_new.b = 9
end
end
The nested function is also there just to replicate the content of my real code. My real code is below, although I've stripped a great deal of it out to shorten it. Changing the value of a in the gui, then pressing OK, should pass the updated variable back to the calling code.
clear
clc
S.a = 1.134
% Open dialogue to get inputs
[not_OK, S_out]=UserInput(S);
S_out.a
function [not_OK, S_new]=UserInput(S_in)
S_new = S_in;
% Get the screen size
screenSize = get(0, 'ScreenSize');
screenWidth = screenSize(3);
screenHeight = screenSize(4);
topOffset = 50;
rightOffset = 50;
not_OK = 1;
% Set figure size
figWidth = 700; % Default MATLAB figure width is 560
figHeight = 650; % Default MATLAB figure height is 420
hfig = figure('Menu','none',...
'Position',[screenWidth-figWidth-rightOffset, screenHeight-figHeight-topOffset, figWidth, figHeight]);
test_list = {'STP','SIN','LFR'};
fcnList = {@calc_axlepercentage, @calc_rollaxis, @calc_cg2raheight};
filePath = pwd; %mfilename('fullpath');
% Set control positions and sizes
tLeft = 20;
eLeft = 260;
tWidth = eLeft - tLeft;
eWidth = 50;
teHeight = 20;
tLeft2 = tLeft + tWidth + eWidth + 5 + eWidth + 10; %360;
eLeft2 = tLeft2 + eLeft - tLeft;
topHeight = figHeight - 60;
% Create GUI
uicontrol('Style', 'text', 'String', 'CG to Fr Axle [m]', 'Parent',hfig, ...
'Position', [tLeft, topHeight-(9.*25), tWidth, teHeight],'HorizontalAlignment','left');
edit_a = uicontrol('Style', 'edit', 'String', S_new.a, 'Parent',hfig, ...
'Position', [eLeft, topHeight-(9.*25), eWidth, teHeight]);
uicontrol('Style', 'pushbutton', 'String', 'OK', ...
'Parent',hfig, ...
'Position', [4*figWidth/6, topHeight-(23.*25), figWidth/6, 2*teHeight],...
'Callback',@ok_fun);
function ok_fun(~,~)
not_OK = 0;
S_new.a = str2double(edit_a.String)
delete(hfig)
end
end
Can you help with why S_out is not receiving the changed value of a?
Thanks.
2 Comments
Stephen23
on 30 Jun 2025
Edited: Stephen23
on 30 Jun 2025
"Can you help with why S_out is not receiving the changed value of a?"
GUIs are fundamentally asynchronous event-based code, but you have not really taken that into account. As Walter Roberson recommended, adding WAITFOR after setting up the UICONTROL might give the behavior that you expect:
But that depends on what you expect: do you want the user to be able to update the structure exactly one time, or repeatedly?
Accepted Answer
Walter Roberson
on 30 Jun 2025
When you create uicontrol, they are created and displayed (if appropriate), and then flow immediately continues onward without waiting. So you call UserInput which creates uicontrols and displays them, but then function UserInput ends, leaving the uicontrol on the screen and returning appropriate output.
The user is not given an opportunity to interact with the uicontrol() until one of the following happens:
- pause() is called
- drawnow() is called
- waitfor() or uiwait() is called
- figure() is called
- keyboard() is called, or control returns to the keyboard
In your situation, flow passes through the UserInput() call and UserInput() returns, the S_out.a happens, and then the flow of execution ends, returning MATLAB to the keyboard -- and finally user interaction is permitted.
Thus, the S_out.a happens before the uicontrol() pushbutton Callback is executed. The update to S_new.a has not happened yet at the time the S_out.a occurs.
When the user presses the pushbutton, tthe nested S_new is updated, affectting the variable stored inside UserInput... but UserInput has already returned.
If you want the pushbutton to have a chance to execute, you should probably call waitfor after creating the uicontrol pushbotton.
Remember to delete or deactivate the pushbotton after it has been clicked, as otherwise it will hang around and uselessly accumulate changes to S_new with no way to get at those changed versions...
0 Comments
More Answers (0)
See Also
Categories
Find more on Migrate GUIDE Apps in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!