I want to stop the execution of script once all window figures are closed (i.e when I manually finish closing each figure window with a click). I tried doing:
x = 1:10;
plot(x,x);
while ~isempty(findall(0,'Type','Figure'))
if isempty(findall(0,'Type','Figure'))
exit
else
continue
end
end
However with the above code i) no figure is displayed and ii) the loop never ends. So my question is: how can exit matlab execution once all figure windows are closed?
Instead of polling in a loop, you can use waitfor
f(1)=figure();
f(2)=figure();
x = 1:10;
plot(x,x);
drawnow;
for ix=1:numel(f)
waitfor(f(ix));
end
All you need is to update callbacks. For this purpose, use drawnow function inside your while loop. If you don't want to exit matlab, do not use exit. Your programm script will stop automatically after it will finish while loop:
x = 1:10;
plot(x,x);
while ~isempty(findall(0,'Type','Figure'))
drawnow
end
Related
I want to detect pressing of the key, when running matlab script in while loop. At the moment, I only want to display success, after pressing of the key. Unfortunately, the message is displayed only after program interruption (CTRL+C) not during program run. Here is the code:
% Init of callback
fig = gcf;
set(fig,'WindowKeyPressFcn',#keyPressCallback);
% keyPressCallback function
function keyPressCallback(source,eventdata)
keyPressed = eventdata.Key;
if strcmpi(keyPressed,'space')
disp('success');
end
end
You need to break the cycle of the script which is running so that Matlab will process other events, in essense your keypress. You can do that by adding a drawnow inside you while loop, the code below should give you enough to incorporate in your own:
fig = figure;
set(fig,'WindowKeyPressFcn',#(hFig,hEvent)fprintf('pressed key %s\n',hFig.CurrentKey) );
drawnow();
while true
if ~ishandle(fig); break; end
drawnow();
end
This question already has answers here:
Stop A GUI in a middle of process in MATLAB
(2 answers)
How can I loop indefinitely, but stop on some condition(s)?
(2 answers)
Closed 4 years ago.
I am writing a matlab script that will perform calculations in a for loop, but would like it to break out of the for loop when 'return' is entered. I found a function that will listen for keystrokes and modified it to know when 'return' is pressed, but I can't figure out how to make it control what is going on in the main script.
Pseudo Code:
h_fig = figure;
set(h_fig,'KeyPressFcn',#myfun)
for ii = 1:50
break when enter is pressed
end
function y = myfun(src,event)
y = strcmp(event.Key,'return');
%disp(event.Key);
if y == 1
fprintf('Enter key pressed')
return
end
end
It seems like you are creating the window only so you can capture the return key press. If this is the case, there is a better alternative: kbhit (in Octave a similar function with the same name comes built-in). Simply copy the kbhit.m file from that File Exchange submission to your current folder (or any directory that you can add to your MATLAB path using addpath), and do as follows:
kbhit('init');
for ii = 1:50
if kbhit == 13
break
end
% computations here...
end
If you want to use a window anyway, the right way to do so is to poll the "CurrentCharacter" property of the figure window:
h_fig = figure;
set(h_fig,'CurrentCharacter','') % use this if the figure has been around for longer, to reset the last key pressed
for ii = 1:50
drawnow % sometimes events are not handled unless you add this
if double(get(h_fig,'CurrentCharacter'))==13
break
end
% computations here...
end
I could not get the above code to work in Octave, it seems that it doesn't update figure properties even with drawnow, not sure why. But I'm fairly sure the above works with MATLAB.
Lately I've started to make a crank mechanism animation. The animation works well, but when I tried to close the Figure 1 window it just keeps popping up.
I don't know how to stop this?
Code:
clc;
clear all;
radius=2;
vzdOdKliky=6;
bod1=[0,0];
axis(gca, 'equal');
mezera=[-4,8,-4,8];
axis(mezera);
speed=1;
for time=1:200
theta=speed*(time/10);
bod2=radius*[cos(theta),sin(theta)];
alfa=asin(radius*sin(theta)/vzdOdKliky);
bod3=[(radius*cos(theta)+vzdOdKliky*cos(alfa)) 0];
klika=line([bod1(1),bod2(1)],[bod1(2),bod2(2)]);
klouzM=line([bod2(1),bod3(1)],[bod2(2),bod3(2)]);
trajB2=viscircles([0,0],radius,'LineStyle',':');
kruhB1=viscircles(bod1,0.3);
kruhB2=viscircles(bod2,0.3);
kruhB3=viscircles(bod3,0.2);
pause(0.001);
delete(klika);
delete(kruhB1);
delete(kruhB2);
delete(kruhB3);
delete(klouzM);
end
Your loop continues regardless of whether you've closed the figure or not.
Include a check on the figure's existence each loop like so:
% Open figure and store to variable for checking later
fg = figure;
% ... your setup code ...
for time = 1:200
% Check if the figure still exists
if ~isvalid(fg)
% Exit looping, figure has been closed
break
end
% ... other code in the loop ...
end
If you wanted to be less elegant, you could always hit Ctrl+C to terminate your script.
I have a program using two timers. The first one allows me to communicate with a microcontroller every second and to update charts, and I use the second one to stop the program after 50 seconds if the user did not press stop button before. The problem is that I don’t know how to wait the end of the execution of the callback function of the first timer before ending the program. Sometimes, it stops in the middle of the first callback. I would like to avoid that, but I don’t know how. I tried to use “waitfor”, but it doesn’t work.
Here is a simple example with the same problem.
t = timer('ExecutionMode','fixedRate','Period', 1,'TimerFcn',#testWait);
fwait = figure('Visible','off');
start(t);
disp('start');
pause(5);
delete(fwait);
i=0;
while true
waitfor(fwait);
disp(int2str(i));
pause(0.05);
i = i + 1;
end
function testWait(src,event)
disp('before');
waitfor(evalin('base','fwait'));
disp('after');
assignin('base','fwait',figure('Visible','off'));
pause(1);
delete(evalin('base','fwait'));
end
Can someone help me please ! :)
You can try using uiwait and uiresume. Here's a code snippet for how to use it:
f = figure;
h = uicontrol('Position',[20 20 200 40],'String','Continue',...
'Callback','uiresume(gcbf)');
disp('This will print immediately');
uiwait(gcf);
disp('This will print after you click Continue');
close(f);
I am using a waitbar like this:
h = waitbar(0,'Please wait...');
for i=1:100, % computation here %
waitbar(i/100)
% other operation here
end
close(h)
I would like to stop this script if the user close the waitbar (clicks the X of the window), without having to add a Cancel button.
Is there any way to do it?
You can test whether h is a valid handle, and exit the loop otherwise. Insert the following into your loop:
if ~ishandle(h)
break
end
You can try something like this :
if ishandle(h),
close(h);
% Your code here
else
%waitbar has been closed by the user
% call throw, return, or break
end
Hope it helps,