GUI remains open while script runs even though close(fig1) is in place.

4 views (last 30 days)
I created a GUI (did not use GUIDE) to ask the user for input. Initially, the script kept running while the GUI was open and before the user had a chance to enter anything. This was solved using uiwait(fig1). Now, the script waits until the user has entered the data and clicks continue, but once the user clicks continue, the GUI does not close until the rest of the scrip has run, which takes some time. It makes it look like MATLAB crashed when it didn't. Am I missing something about uiwait or uiresume?
Any help would be greatly appreciated! Thanks!
Here's the GUI code:
function GUI_getFuelData
% Enter fuel information.
% Create GUI figure
[Input fields/fig left out for readability sake]
% Continue button
pButton = uicontrol('Parent',fig1,...
'Style','pushbutton',...
'String','Continue',...
'Units','pixels',...
'Position',[135 10 60 30],...
'Callback', @pButtonCallback);
%%Update GUI
movegui(fig1,'center')
% Make the GUI visible.
set(fig1,'Visible','on');
uiwait(fig1);
%%Callback
function pButtonCallback(hObject, eventdata)
% Callback function to retrieve entered data and continue the
% program.
dieselCost = str2double(get(hDieselCostEdit, 'String'));
dieselLHV = str2double(get(hDieselLHVEdit, 'String'));
dieselDensity = str2double(get(hDieselDensityEdit, 'String'));
assignin('base', 'dieselCost', dieselCost);
assignin('base', 'dieselLHV', dieselLHV);
assignin('base', 'dieselDensity', dieselDensity);
natGasCost = str2double(get(hNatGasCostEdit, 'String'));
natGasLHV = str2double(get(hNatGasLHVEdit, 'String'));
natGasDensity = str2double(get(hNatGasDensityEdit, 'String'));
assignin('base', 'natGasCost', natGasCost);
assignin('base', 'natGasLHV', natGasLHV);
assignin('base', 'natGasDensity', natGasDensity);
close(fig1);
end
end

Accepted Answer

Geoff Hayes
Geoff Hayes on 14 Nov 2014
Jonathan - you haven't included the uiresume in your above code so it isn't clear how the "wait" is cancelled. If you had put the uiresume in your callback (which would follow the example at Block program execution and wait to resume) and the close outside of the callback (in the part of the script that should execute) then this perhaps would work as you expect it to. When I try to run the above (after commenting out all code in the callback, except for last line), then once close(fig1) is called, the figure closes without delay. You mention how this doesn't happen, so that may be due to specific code that you have not shown which follows.
You also mention that you use uiwait because the the script kept running while the GUI was open and before the user had a chance to enter anything. If I were to use a similar script for a GUI (typically I just use GUIDE), then my script would contain only code that creates the GUI, the widgets, provides the callbacks, and nothing else. There wouldn't be any logic that follows (should be run) outside/after any of the widgets have been created. All code would be embedded in a callback or a function that a callback calls..
I suggest that you try the same - take all code that follows your uiwait and either put it in a separate function that can be called from pButtonCallback or add it to the body of pButtonCallback, following the
assignin('base', 'natGasCost', natGasCost);
assignin('base', 'natGasLHV', natGasLHV);
assignin('base', 'natGasDensity', natGasDensity);
lines of code. Then remove the uiwait and uiresume, and just have this GUI remain open until all work has been completed. If you want the user to know if something is "happening" behind he scenes, then just change the mouse pointer to a watch (hourglass?)
function pButtonCallback(hObject, eventdata)
% change mouse pointer image/icon
set(fig1,'Pointer','watch');
dieselCost = str2double(get(hDieselCostEdit, 'String'));
dieselLHV = str2double(get(hDieselLHVEdit, 'String'));
% etc.
assignin('base', 'natGasCost', natGasCost);
assignin('base', 'natGasLHV', natGasLHV);
assignin('base', 'natGasDensity', natGasDensity);
% do other stuff
% other stuff is finished so change mouse pointer back to arrow
set(fig1,'Pointer','arrow');
% close the GUI
close(fig1);
end
Try the above and see what happens!
  3 Comments
Cou
Cou on 18 Nov 2014
Update: I ran the script and called the GUI function. uiresume causes an empty figure to open... It seems that the GUI function allows the user to input data, click 'continue' then the script that contains the GUI function runs, then the uiresume is invoked. I think I'm missing a key point about functions here...?
Geoff Hayes
Geoff Hayes on 18 Nov 2014
Jonathan - I think you were right that you don't really need a uiresume as you correctly state
..however the documentation says "uiwait(h) blocks execution until uiresume is called or the figure h is deleted"
So when you close the figure with close(fig1); that causes it to be deleted and the blocking "wait" is released.
I'm a little surprised that the uiresume causes a new figure to open (I've replicated the same behaviour as your). If you look at the code in uiresume.m, you will see the lines
if nargin < 1,
hFigDlg = gcf;
end
Since you are not passing any arguments with uiresume, then nargin is zero, and so the above condition is true. The call to gcf (which is get current figure) returns the current figure - and if one doesn't exist, then it creates one).
I think that you could do the following if you wanted to use uiwait and uiresume
uiwait(fig1);
function pButtonCallback(hObject,eventdata)
% do stuff
% resume
uiresume(fig1);
end
close(fig1);
Note the above uses fig1 as an input to all three functions.
As for calling other GUIs after this one closes, you should be able to launch a new GUI from the above button callback. Just close the current GUI with close(fig1) and then call the script to open the second/next GUI.

Sign in to comment.

More Answers (1)

Cou
Cou on 18 Nov 2014
FWIW, MATLAB's example of uiwait does the same thing my code does... If you use function
function GUITest
f = figure;
h = uicontrol('Position', [20 20 200 40], 'String', 'Continue', ...
'Callback', 'uiresume(gcbf)');
disp('This will print immediately');
uiwait(gcf);
disp('This will print after you click Continue'); close(f);
Then call it with a for loop after (Just to simulate a script running after the GUI closes), it still leaves the window open until the loop finishes.
E.g.
GUITest; for x = 1:50000
disp(x)
end
I suppose I will resort to putting my entire script in the GUI function.

Categories

Find more on Interactive Control and Callbacks in Help Center and File Exchange

Products

Community Treasure Hunt

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

Start Hunting!