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

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)

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

BRILLIANT, thanks a lot Guillaume.
Hi Guillaume,
One final question, please. If I have an EditField box in my app whre I want the inputted string called from the "mytimercallback(~, ~, ~)" function.
I would prefer to have a function inside the "mytimercallback(~, ~, ~)" function.
How can I do this? I have modified you code a bit and included it here as app1new. When I run it i get the following error message:
This message is sent at time 19:19:16.520
Error while evaluating TimerFcn for timer 'timer-1'
Undefined variable "app" or class "app.EditField.Value".
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
Once again, thanks for you great help Guillaume

Sign in to comment.

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

Note that the Value property of a StateButton is either 0 or 1. It's not the same as its Text property. There's also not much point in the Inprocess indirection, you may as well do the timer start/stop inside the switch (or better an if|):
function SwitchValueChanged(app, event)
if app.Switch.Value
app.InProcessLamp.Color = 'green';
start(app.Timer);
else
app.InProcessLamp.Color = 'red';
stop(app.Timer);
end
end
Hi Geoff Hayes and Guillaume, thanks a lot for your help. What I really want is have a switch tuning on or off a "watch" function such as when the switch is turned on I want to monitor a folder say "Myfolder" and when i file is placed in the "Myfolder" it will move it to a new folder called "Finalfolder". I thougt I while loop could do the trick, but do you have a better suggestion?
Thanks
Johnny - why not use a timer to do that? It can periodically "monitor" your folder and move any files found there to the new folder destination. When finished, you could turn the timer off.
Hi Geoff, I would like to use a timer for this, I just not know how. I need to Myfolder to be monitores every 5 sec until I turn the switch to 'Stop' position
Johnny - take a look at the documentation for the timer object. You will need to do something like
function SwitchValueChanged(app, event)
if app.Switch.Value
% start your timer
t = timer;
t.Period = 35
t.TimerFcn = @myTimerCallback;
start(t)
% save the timer object to the app
% ???
else
% stop your timer
% get your timer object from the app
% ???
t = ...;
stop(t);
end
end
function myTimerCallback(mTimer, ~)
% query your folder for new files
% move the new files
end
I'm just not sure on how to save the timer object to the app. It could be as simple as doing app.timerObj = t; but I haven't used App Designer to know for sure.
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.
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 Code Execution in Help Center and File Exchange

Products

Release

R2019a

Asked:

on 2 Jun 2019

Commented:

on 4 Jun 2019

Community Treasure Hunt

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

Start Hunting!