Hi, i am making a animation but i want to be able to pause it when i press space and continue again when i press space (just like youtube). This is what i have but im not sure what to put in the while loop.
function myfun(~,event)
if event.Key == "space"
pause(0.1)
while event.Key ~= "space"
end
end
end
I feel like a simaler function needs to be inside the while loop but if i try that i get an error. Currently this function works as a press switch and not as a latch. And the pause doesnt work great either, once in a while it still continues a frame if i hold space. I'm not sure if the explanation is clear, so i attached the .m file.

 Accepted Answer

Voss
Voss on 10 Feb 2024
Try the attached m-file. See if it works as expected and makes sense.

8 Comments

It works great!
But I don't know exactly how it works and have a fe questions: I don't understand where it loops while paused. What does the '~' do before 'strcmp' (I assume it checks if the statement is true).
~ is "logical not".
@Dirk te Brake: Walter is correct; ~ is "logical not", so this part
if ~strcmp(event.Key,'space')
return
end
checks that the key pressed was the space key, and if not, the function returns (i.e., no action is taken). Your construction of
if event.Key == "space"
% do stuff
end
would have also worked, but I was writing in MATLAB R2016b, which is before using double-quotes to construct strings was allowed, so it would've been
if strcmp(event.Key,'space')
% do stuff
end
which also would work. I chose to write it such that it returns early in case the key pressed is not the space key because I think it makes it clear that the only situation when the function does anything is when space is pressed, but that's really a stylistic choice.
As for your other question, there is no loop when paused. The keyPressFcn uses uiwait to pause the execution, uiresume to resume the execution, and a variable (is_going) to know whether the thing is currently running (is_going it true) or currently paused (is_going is false), so it knows what to do when space is pressed. There are various ways to have access to the variable is_going inside the keyPressFcn without using a global variable; the approach I chose was to make that function nested inside the GUI function (which required changing the script into that GUI function).
@Dirk te Brake: For your reference, I'm attaching another version of the code that should also work, which is closer to your original. It's also using a nested keyPressFcn inside an outer function (like the code in my answer), but this is using refreshdata(fig,'caller') to refresh the lines' data, similar to your original refreshdata call, except now the lines' source variables are not in the base workspace, so using the 'caller' option is necessary (and therefore it's necessary to specify the first argument (the target object) as well, which in this case is fig).
Thank you for the additional explanantion. I'm not sure if my understanding of how uiwait and uiresume is right but this is how i think it works: When space is pressed the state of the figure is saved in 'src' including the fact that space has been pressed and now it waits untill that same state occurs. But i cant figure out how uiresume would get triggered because the script is waiting at line 4. I ran the function with some disp commands and it appears that the second disp only get triggerd after space is pressed (because the value of 'is_going' should've been 0). So how do both uiwait and uiresume work at the same time.
if is_going % line 1
is_going = false; % 2
disp(is_going) % 3 First disp
uiwait(src) % 4
disp(is_going) % 5 Second disp
else % 6
is_going = true; % 7
disp(is_going) % 8 Third disp
uiresume(src) % 9
end % 10
Outcome when runned:
0
Press space
1
1
"the state of the figure is saved in 'src' including the fact that space has been pressed"
The first part of that statement is kind of correct, but the second part (from "including ...") is not.
'src' is the figure (src == fig), so you can get any information about the figure the same as you could using 'fig', but 'src' does not contain any information about whether or not space has been pressed (neither does 'fig'). That's why you need the separate 'is_going' variable.
"now it waits untill that same state occurs"
No.
"i cant figure out how uiresume would get triggered"
uiresume is called when the space key is pressed and 'is_going' is false.
By way of further explanation, here are some comments for each line of that part:
if is_going % if the for loop in the main function is running
% (i.e., not currently uiwait-ing)
is_going = false; % set is_going to false, so that the next time
% this function is executed when space is pressed,
% execution goes into the else block of this
% function and uiresume will be called.
uiwait(src) % pause execution of all code until uiresume is
% called or the figure (src) is deleted
else % if the for loop in the main function is not running
% (i.e., currently uiwait-ing)
is_going = true; % set is_going to true, so that the next time
% this function is executed when space is pressed,
% execution goes into the if block of this
% function and uiwait will be called.
uiresume(src) % resume execution of code
end
Thank you for the clarification.
You're welcome! Let me know if you have any other questions.

Sign in to comment.

More Answers (1)

You have the difficulty that the event field is not going to update as long as you are inside the KeyPressFcn handler.
You will have to do something along the lines of setting a control variable to indicate "go ahead", and then inside the keypress fnc handler, set the control variable to "pause" if it is currently "go ahead" and space is detected, but set it to "go ahead" if it is currently "pause" and space is detected. The control loop would look something like
while TheControlVariable == "pause"
pause(); %to give a chance for the KeyPressFcn handler to activate
end

1 Comment

The frequent use of "go ahead" confuses me, is it possible to explain it in a different way? This is what i came up with and it works but makes use of global variables.
global Action
Action = "";
% Within the animation loop
if Action == "space"
Action = "pause";
while Action ~= "space"
set(fig,'KeyPressFcn',@myfun);
pause(0.5)
end
Action = "Go ahead";
end
function myfun(~,event)
global Action
Action = event.Key;
end
I rather use something without global variables. So i made this, but it only works if you press any other key than 'space' the second time.
function myfun(~,event)
if event.Key == "space"
Action = 0;
while Action == 0
Action = waitforbuttonpress;
end
end
end
Do you have any idea's or tips on how to get rid of the global variable?

Sign in to comment.

Categories

Find more on View and Analyze Simulation Results in Help Center and File Exchange

Asked:

on 9 Feb 2024

Commented:

on 11 Feb 2024

Community Treasure Hunt

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

Start Hunting!