How do i tell App Designer to wait for a variable to assume a specific value without pausing the execution of other callbacks?

9 views (last 30 days)
I am trying to implement an exit button in my Appdesigner code which deletes the app. The app consists of two sub-apps, one that is used to set a few parameters and calls a function in the other app, and one that calculates the needed data in a for loop function, under the condition that my "Stop" flag is not set to 1 by pressing the corresponding "Stop" button. Once this "Stop" button is pressed, it takes a few queued up loop iterations until the loop is terminated. If i press the "Stop" button and click "Exit", the app is deleted without an error message. However, if i only click the "Exit" button, i get an "invalid or deleted object" error regarding my loop function, presumably since there was not sufficient time to execute the last few loop iterations before it terminates. The "Exit" button essentially does the same thing as the "Stop" button, except it also deletes the app. I have an additional "Run" flag that is 1 if the loop is running and 0 when it is stopped manually or finishes.
I tried using the waitfor command or the uiwait command, but both of these stop the execution of the loop function and thus it cannot terminate correctly, so the error persists. A while loop that breaks once the "Run" flag is 0 also does not work. My question is now: How can i get my app to wait with the deletion of the app until the loop function is terminated?
The function:
function updateplot(app, mXL0, mSL0, uw, YXS, mXLend, tend, FR1, VL1, VLmax, CSR)
% Calculate mXL(t) and mSL(t) and plot data
i = app.i_start;
app.mXL(1) = app.mXL0;
app.mSL(1) = app.mSL0;
app.FR(1) = app.FR1;
app.VL(1) = app.VL1;
app.t_plot(1) = 0;
app.timit = app.tend/1000;
app.RunFlag = 1;
for t = app.t_start:app.timit:tend
if app.Stop ~= 1
if app.DialogApp.StopNow ~= true
app.t_plot(i) = t;
app.FR(i) = app.FR(1).*exp(app.uw.*app.t_plot(i));
app.VL(i) = app.VL(i-1)+app.timit.*app.FR(i);
app.mXL(i) = app.mXL(1).*exp(app.uw.*app.t_plot(i));
app.mSL(i) = app.mSL(i-1)-(app.mXL(i)-app.mXL(i-1))./app.YXS+(app.VL(i)-app.VL(i-1)).*app.CSR;
yyaxis(app.UIAxes,'left')
app.Plot1 = plot(app.UIAxes,app.t_plot,app.mXL,app.t_plot,app.mSL);
yyaxis(app.UIAxes,'right')
app.Plot2 = plot(app.UIAxes,app.t_plot,app.FR,app.t_plot,app.VL);
i = i+1;
pause(360.*app.timit./app.increment)
else
app.Stop = 1;
end
else
% Store last time point and index i if plot is
% paused
app.t_start = t;
app.i_start = i;
app.RunFlag = 0;
break
end
drawnow
end
app.RunFlag = 0;
end
The "Stop" button:
% Pause execution of loop upon button push event
if app.StopButton.Text == "Pause"
app.Stop = 1;
app.StopButton.Text = "Resume";
else
% Resume plotting and loop execution where it was left off
app.Stop = 0;
app.StopButton.Text = "Pause";
updateplot(app, app.mXL0, app.mSL0, app.uw, app.YXS, app.mXLend, app.tend, app.FR1, app.VL1, app.VLmax, app.CSR);
end
The "Exit" button:
% Stop data saving and pause loop execution
if app.Stop == 0
app.Stop = 1;
end
while app.RunFlag == 1
drawnow
if app.RunFlag == 0
break
end
end
delete(app)
I am very grateful for any help!

Accepted Answer

Monica Roberts
Monica Roberts on 3 May 2022
You could have your exit button simply toggle RunFlag, and then in your "updateplot" function for loop you can check the flag and delete the app. I would suggest only modifying the RunFlag in a startup function rather than modifying it within your updateplot function. Then just check the flag every loop:
for t = app.t_start:app.timit:tend
if app.RunFlag == 0
delete(app)
end
if app.Stop ~= 1
%ETC
The exit button callback can just be:
app.RunFlag = 0;

More Answers (0)

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!