Managing App Closure: Control When Users Can Exit Your MATLAB App

Adam Danz on 29 Apr 2025 at 14:37 (Edited on 29 Apr 2025 at 16:13)
Latest activity Reply by Adam Danz on 2 May 2025 at 13:34

The topic recently came up in a MATLAB Central Answers forum thread, where community members discussed how to programmatically control when the end user can close a custom app. Imagine you need to prevent app closure during a critical process but want to allow the end user to close the app afterwards. This article will guide you through the steps to add this behavior to your app.
A demo is attached containing an app with a state button that, when enabled, disables the ability to close the app.
Steps
1. Add a property that stores the state of the closure as a scalar logical value. In this example, I named the property closeEnabled. The default value in this example is true, meaning that closing is enabled. -- How to add a property to an app in app designer
properties (Access = private)
closeEnabled = true % Flag that controls ability to close app
end
2. Add a CloseRequest function to the app figure. This function is called any time there is an attempt to close the app. Within the CloseRequest function, add a condition that deletes the app when closure is enabled. -- How to add a CloseRequest function to an app figure in app designer
function UIFigureCloseRequest(app, event)
if app.closeEnabled
delete(app)
end
3. Toggle the value of the closeEnabled property as needed in your code. Imagine you have a "Process" button that initiates a process where it is crucial for the app to remain open. Set the closeEnabled flag to false (closure is disabled) at the beginning of the button's callback function and then set it to true at the end (closure is enabled).
function ProcessButtonPress(app, event)
app.closeEnabled = false;
% MY PROCESS CODE
app.closeEnabled = true;
end
Handling Errors: There is one trap to keep in mind in the example above. What if something in the callback function breaks before the app.closeEnabled is returned to true? That leaves the app in a bad state where closure is blocked. A pro move would be to use a cleanupObj to manage returning the property to true. In the example below, the task to return the closeEnabled property to true is managed by the cleanup object, which will execute that command when execution is terminated in the ProcessButtonPress function—whether execution was terminated by error or by gracefully exiting the function.
function ProcessButtonPress(app, event)
app.closeEnabled = false;
cleanupClosure = onCleanup(@()set(app,'closeEnabled',true));
% MY CODE
end
Force Closure: If the CloseRequest function is preventing an app from closing, here are a couple of ways to force a closure.
  1. If you have the app's handle, use delete(app) or close(app,'force'). This will also work on the app's figure handle.
  2. If you do not have the app's handle, you can use close('all','force') to close all figures or use findall(groot,'type','figure') to find the app's figure handle.
Steven Lord
Steven Lord on 30 Apr 2025 at 23:20
With my software quality engineer hat on, to be extra careful I would query the state, set up the onCleanup object to restore that state, and then change the state.
The order of the first two steps ensures that even if someone changes the default value from true to false, my code wouldn't need to change. But the original version would now be incorrect, it would reset the state to a different value than it had previously.
The order of the second two steps safeguards against what are in this case very unlikely events, someone hitting Ctrl-C exactly between the two lines of code in ProcessButtonPress, the call that creates the onCleanup object throwing an error, or some other factor interrupting execution of the function before the onCleanup object was completely and successfully created. If there were more lines between changing the state and creating the onCleanup, or if the onCleanup call were more complicated, I'd be more concerned.
Adding that one extra step does make the code one line longer, but IMO that one additional line is pretty simple and self-explanatory.
% original
function ProcessButtonPress(app, event)
app.closeEnabled = false;
cleanupClosure = onCleanup(@()set(app,'closeEnabled',true));
% MY CODE
end
% mine
function ProcessButtonPress(app, event)
oldstate = app.closeEnabled;
cleanupClosure = onCleanup(@()set(app,'closeEnabled',oldstate));
app.closeEnabled = false;
% MY CODE
end
Trying to be clever and skipping creating that variable by including that code in the onCleanup object's cleanup function wouldn't work. As written below, when the onCleanup object was destroyed MATLAB would query the value of the app's closeEnabled property at that time and set the app's closeEnabled property to that same value. So nothing would change. The oldstate variable in the code above exists so MATLAB effectively "remembers" the value of that property when the onCleanup object was created rather than asking for the value to reset the property to when the onCleanup object is destroyed.
% Would not work
function ProcessButtonPress(app, event)
cleanupClosure = onCleanup(@()set(app,'closeEnabled',...
app.closeEnabled));
app.closeEnabled = false;
% MY CODE
end
Adam Danz
Adam Danz on 2 May 2025 at 13:34
+1 to creating the onCleanup object before changing the state!
goc3
goc3 on 30 Apr 2025 at 14:32
I did not know that I needed this feature until Adam presented it, and in a straightforward way, as always.
I have the confirm-exit setting toggled on in many apps, including MATLAB and browsers. I am sure that we have all accidentally closed an app just to have to reopen it.
It is very easy to use uiconfirm within the UIFigureCloseRequest callback to create this same confirm-exit behavior for any apps we create. In fact, I have already done so in the one I am working on right now.
Image Analyst
Image Analyst on 29 Apr 2025 at 15:34
Nice tip! 🙂