Separate Callback Functions in AppDesigner

31 views (last 30 days)
dpb
dpb on 26 Apr 2025 at 16:15
Edited: dpb on 27 Apr 2025 at 16:20
Having defined a callback function for an application "Quit" button, it was also assigned to be the CloseRequestFunction callback. I've now determined I really need to separate those to avoid potential issues if the user were to try to close the app while processing.
However, AppDesigner only renames the one existing callback function; it will not allow me to now create a new callback for either action and since the callbacks are in the protected section, one can't add a new function manually.
How can one disassociate the CloseRequestFunction and QuitButton callbacks from the one present function to have two independent callbacks?
ADDENDUM
There is a workaround; one can parse the passed event stuct and determine which object is the instigator and thus branch inside the one callback function.
But, unless there is some other way to edit the app file short of deleting and recreating controls, it seems to be a hole in the AppDesigner user interface.
  4 Comments
Cris LaPierre
Cris LaPierre on 27 Apr 2025 at 1:07
Edited: Cris LaPierre on 27 Apr 2025 at 2:09
I suppose maybe the way out would be to select <no callback> for one and then it would let me create a new one?
Yes, that is what I would do.
You could also create the function in the app first. It would then appear in the dropdown list, where you could select it as the callback for that control.
dpb
dpb on 27 Apr 2025 at 16:19
Edited: dpb on 27 Apr 2025 at 16:20
"Yes, that is what I would do."
Thanks for confirmation, assurance, Cris. I wasn't positive where that would end up leaving me so was hesitant to just go ahead, but it did then work as expected/hoped...I observe that when one makes those changes, AppDesigner modifies the callbacks section comments to match...I didn't try the add a function route...
Now if I can just work out all the cleanup logic needed owing that I didn't think about this scenario in the beginning so at the moment don't have handles to what could be an activex server with an open file that it's decorating the formatting inside...or figure out a way for a brief notification to the user why being ignored that will actually happen in time...the uiXXX routines that all need a user action to close don't fit the need here and using a uiwait on a msgbox is less than satisfactory because it cannot be a child of the UIFigure and often ends up behind the app figure instead on top of which even if is, then the UIFigure loses focus. None of the workarounds I've found appear to be reliable; this has been an issue "since forever" it seems from searching.
As an aside, during my working/consulting career I never wote UIs; I had specialists to deal with those while I solved the underlying algorithms and wrote that code. Hence, this is a new arena for me and I'm finding getting all the little nits out of app behavior very time consuming and painful...I appreciate Eric and his crew even more now than did back then! <vbg>

Sign in to comment.

Answers (1)

Image Analyst
Image Analyst on 26 Apr 2025 at 18:20
The callback for a button, and the CloseRequestFunction callback for the figure are two entirely separate functions. For the Quit button you should see a function like
function QuitButtonPushed(app, event)
% Quit without asking user for confirmation.
delete(app);
end
For the close request function you should see something like
% Close request function: UIFigure
function CloseRequestFcn(app, event)
% Ask user if they really want to exit the program.
promptMessage = sprintf('Do you want to quit this program?');
titleBarCaption = 'Quit?';
buttonText = questdlg(promptMessage, titleBarCaption, 'Yes - Quit', 'No - Continue', 'No - Continue');
if contains(buttonText, 'Quit', 'IgnoreCase', true)
delete(app) % Shut down program
end
% Else you get here and the program will continue.
end
I have no idea why they are the same function for you. Can you attach your .mlapp file?
  1 Comment
dpb
dpb on 26 Apr 2025 at 20:05
Edited: dpb on 26 Apr 2025 at 20:07
They're now the same @Image Analyst because my initial thought was they could/should be the same functionality so I set both callbacks to point to the same function; it wasn't until later (like now) I realized about the issue of being able to close the app while still processing and have open files that may even include an active COM session that then can leave stuff hanging. With enough error handling, one should be able to still manage to clean up, but it would be pretty complex now, so if can just prevent it is the expedient.
On retrospect and if it hadn't been the very first "real" app I built, I would have kept the two separate callback functions and just factored them to call the common code, but I wasn't that clever back then.
The response of simply returning is certainly one way and what have done at the moment; this is related to the other thread about the user notification; I had the thought it would be agoodthing™ to let the user know, so I coded up a uialert but it didn't show up until after everything else was gone and there's no way with them to have it be just a short display message and then go away because there is no handle can use with uiwait with these (another big oversight, it seems). The venerable msgbox and friends do, but they aren't and can't be children of the app uifigure and there's the issue with them of not always being in focus in front of the GUI.
Since it is a rare event, I'll just take the expedient route and silently ignore the request as you suggest.
I don't want to make the app window full screen because it is a very small footprint of just a few textboxes in which to select some files and a couple of buttons so would be pretty ugly and unecessary to take up the whole screen plus I think it's "just plain rude" to take over a user's whole screen with an app as if it were the only thing going on. It does save and restore itself to the last location and state the user left it when previously used so that would also destroy that feature.
Thanks for the feedback...without the whole mlapp file, there's the callback section for the exit callbacks as AppDesigner now show it...the comments and the function definition and end statements are in the uneditable section of the file, of course.
This has the try for the alert to see how it would work to try to notify user, that was less than satisfactory...the check for the 'Close' event instead of 'Quit' button works well, so I can just comment out the uialert and go on...
% Callback function: BuildFoundSheetToolUIFigure, ExitMenu,
% QuitButton
function QuitButtonPushed(app, event)
if matches(event.EventName,'Close')
if app.inProgress
uialert(app.BuildFoundSheetToolUIFigure,'Cannot close. In progress.','Close Request')
return
end
end
SaveUserSettings(app)
fclose('all');
delete(app)
end
I wouldn't have gotten into it other than I'm having a very bizarre symptom that the app works perfectly on the development machine in the compiled or interactive mode and I can execute the same executable with the network shared files, but when it is installed and run from a machine on the college network, it hangs up with no error or indication of what is the failure. It's even more puzzling because I have a second app built on essentially the same core that does quite similar things on just a different set of Excel files and it works perfectly on the same college network machine. I was looking for anything I could find that had any noticeable difference between the two and then just thought about the "what if" if the user did either accidently or purposely tried to close it while it still had files open...
I'm at a complete loss and not having either admin privileges nor MATLAB installed on the target machine makes it tougher to try to debug...

Sign in to comment.

Categories

Find more on Maintain or Transition figure-Based Apps 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!