How do I break while loop using a switch in app designer

13 views (last 30 days)
I'm working on a GUI using App Designer. I want to control an continues while loop from a switch. So far I can initiate the loop by turning the switch to "go" (see code below) but I am unable to break the loop when I switch it to "stop". I get the 'STOP' printed to my command window, but it then contiues to count.
The output I get is "1234STOP567..." where the while loop contines until i manually break it [ctrl+c].
How do I break the while loop when I turn the switch to 'Stop'?
Thanks
% Value changed function: Switch
function SwitchValueChanged(app, event)
switch app.Switch.Value
case 'Go'
app.InProcessLamp.Color = 'green';
InProcess = 1;
case 'Stop'
app.InProcessLamp.Color = 'red';
InProcess = 0;
end
n = 0;
while true
pause(2)
if InProcess == 0
fprintf('STOP'); %skal fjernes
break;
end
n = n+1;
fprintf(num2str(n));
pause(2);
end
end

Answers (2)

Guillaume
Guillaume on 2 Jun 2019
As I said, a much cleaner design is to have the timer as an App property and initialise it int the StartupFcn. The only thing you'd do in the callback is start and stop it instead of creating and destroying timers.
The default 'ExecutionMode' of timers is 'SingleShot' so they only execute once. If you want a periodic timer you need to specify a different execution mode such as 'FixedRate'.
Attached an example App.
  4 Comments
Guillaume
Guillaume on 4 Jun 2019
mytimercallback is a class method like any other so its first input (which I ignored since we werent' using it) is going to be the app. The only thing you have to do is not ignore it:
function mytimercallback(app, ~, ~)
%code that uses the app input argument
end

Sign in to comment.


Geoff Hayes
Geoff Hayes on 2 Jun 2019
Johnny - without knowing how SwitchValueChanged is called, I suspect that the problem might be because this function ends up being called twice: the first time when the app.Switch.Value is true and the second time when this variable is false. So the first call to this function keeps going "forever" since it is not aware of the change to app.Switch.Value while the contribution of the call to this function a second time is to just to write STOP to the console and it will have no impact on the while loop that is continuing in the first call to this function.
With GUIDE, you could get around this problem by querying - on every iteration fo the while loop - the state of the app.Switch.Value (assuming this value was accessbile from a uicontrol or through an updated copy of the handles structure. For App Designer, I'm not sure how you would do this (continually check the state of app.Switch.Value from within the while loop??)
Alternatively, you may want to consider using a timer object instead of a while loop which would mean that your SwitchValueChanged would become something like
function SwitchValueChanged(app, event)
switch app.Switch.Value
case 'Go'
app.InProcessLamp.Color = 'green';
InProcess = 1;
case 'Stop'
app.InProcessLamp.Color = 'red';
InProcess = 0;
end
if InProcess
% start your timer
else
% stop your timer
end
end
You would need to save the handle to the timer object (somewher in the app) so that you can stop it. Note that once you start the timer, your call to SwitchValueChanged will complete so that the next time you call this function, there will not be an already running call of it.
  7 Comments
Guillaume
Guillaume on 2 Jun 2019
Apps are just classes, you'd define the timer as a property of the class, and initialise it in the App StartupFcn.
Note that if on Windows, I'd consider using .Net FileSystemWatcher instead of a Timer. There are a few examples on Answer on how to do that (this is one of mine). For all OSes, you can also use Java WatchService but it's more complicated. See this Answer where I worked it out.
The advantages of the watchers is that you don't have to do any polling, you just wait to get notified that the file has changed.
Johnny Birch
Johnny Birch on 2 Jun 2019
Once again, thanks for you help.
I have one last issue. I can call the function by use of Geoff's code modified to below code, but I would expect the code to run my function every 2 second and therefore give a updatede timestamp in the Command Window. But I only get the first timestamp when I switch in on, but no following timestamps. What am I missing?
% Value changed function: Switch
function SwitchValueChanged(app, event)
switch app.Switch.Value
case 'Go'
app.InProcessLamp.Color = 'green';
InProcess = 1;
case 'Stop'
app.InProcessLamp.Color = 'red';
InProcess = 0;
end
assignin('base','InProcess',InProcess);
% start your timer
t = timer;
if InProcess == 1
t.Period = 2;
t.TimerFcn = @myTimerCallback;
start(t)
out = isvalid(t);
else
stop(t)
delete(t)
out = isvalid(t);
end
assignin('base','out',out);
function myTimerCallback(t, ~)
% query your folder for new files
fprintf('This message is sent at time %s\n', datestr(now,'HH:MM:SS.FFF'));
% move the new files
end

Sign in to comment.

Categories

Find more on Develop Apps Using App Designer in Help Center and File Exchange

Products


Release

R2019a

Community Treasure Hunt

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

Start Hunting!