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);
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
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
In a Matlab function, I would like to know the last time a user interacted with the Matlab GUI. By matlab GUI, I mean basically, a user typing in the command window, or in the editor.
The algorithm I wish to implement is essentially:
If it's been a while, the function will not grab focus, but operate in the background.
If the user has recently interacted, presumably he/she is interested "right now" in the results, and the function will grab focus.
This is a tough one ! Here is a proposition to do what you want with the command window only, based on this undocumented code and persitent variables.
I used two functions: CW_listen and CW_callback. A call to CW_listen (or CW_listen(true)) starts to listen to the command window, while a call to CW_listen(false) stops listening. While listening is on, any action performed on the command window trigs a call toCW_callback.
Here are the two functions:
function CW_listen(b)
% Default value
if ~exist('b', 'var'), b = true; end
% Get the reference handle to the Command Window text area
jDesktop = com.mathworks.mde.desk.MLDesktop.getInstance;
try
cmdWin = jDesktop.getClient('Command Window');
jTextArea = cmdWin.getComponent(0).getViewport.getComponent(0);
catch
commandwindow;
jTextArea = jDesktop.getMainFrame.getFocusOwner;
end
% Instrument the text area's callback
if b
set(jTextArea,'CaretUpdateCallback',#CW_callback);
else
set(jTextArea,'CaretUpdateCallback',[]);
end
and
function CW_callback(varargin)
% Define a persistent variable
persistent last_call;
if isempty(last_call)
last_call = clock;
else
ts = clock;
Dt = etime(ts, last_call);
% Update the status bar
dt = javaMethod('getInstance', 'com.mathworks.mde.desk.MLDesktop');
if dt.hasMainFrame
dt.setStatusText(['Ellapsed time: ' num2str(Dt) 's']);
end
if Dt>5
fprintf('So long !\n');
last_call = ts;
else
% Do nothing
end
end
I also dislayed the ellapsed time in the status bar, it was useful for developping the code and adds a quite cool feature.
You can replace the time in seconds (here 5s) and the fprintf('So long !\n'); by any action of your choice. Be aware that inserting any kind of display outside of this if statement will result in an infinite display loop ...
For the moment I don't see how one could transpose this to the editor, but if you search in Undocumented Matlab you may find how to do it ;)
I have 2 pushbutton. If i press one infinte loop will be running and if i press other loop must break. please some help in code.
Thanks in advance
Are you using GUIDE or a "programmatic" gui? The following is a little example for a programmatic gui; similar concepts may apply for GUIDE. (I personally like the added flexibility of the programmatic gui route, plus I always end up irrevocably breaking any GUIDE gui's I create...)
Anyway, a few things to note in this example:
use of the gui's figure handle UserData field to store "global" information. This is a way to pass data between callbacks.
the pause statement within the "infinite" loop is needed so that the interrupt from cb_button2 is processed. From Matlab help: "If the Interruptible property of the object whose callback is executing is on , the callback can be interrupted. However, it is interrupted only when it, or a function it triggers, calls drawnow, figure, getframe, pause, or waitfor."
function my_gui(varargin)
mainfig = figure;
out.h_button1 = uicontrol(mainfig,...
'Style','pushbutton',...
'Units','Normalized',...
'Position',[0,0.5,1,0.5],...
'String','Button 1',...
'Callback',#cb_button1);
out.h_button2 = uicontrol(mainfig,...
'Style','pushbutton',...
'Units','Normalized',...
'Position',[0,0,1,0.5],...
'String','Button 2',...
'Callback',#cb_button2);
out.button2_flag = 0; %flag indicating whether button 2 has been pressed yet
set(mainfig,'UserData',out);%store "global" data in mainfig's UserData (for use by callbacks)
function cb_button1(varargin)
out = get(gcbf,'UserData'); %gcbf: handle of calling object's figure
while ~out.button2_flag
disp('Aaaahhh, infinite loop! Quick press Button 2!');
out = get(gcbf,'UserData'); %reload "global" data
pause(0.1); %need this so this callback may be interrupted by cb_button2
end
disp('Thanks! I thought that would never end!');
function cb_button2(varargin)
out = get(gcbf,'UserData'); %gcbf: handle of calling object's figure
out.button2_flag = 1;
set(gcbf,'UserData',out); %save changes to "global" data
My GUI's aim is to show images and to get a response from the user: either a key press (E or I) or no response. Between the images themselves there should be a 3 second pause showing some text (a7 UIcontrol in my code). The problem is that I need to do it for 30 times, so I use a loop with a timer inside it. But the GUI works badly..
It should do the following:
for 30 times do
2 sec showing text (a7)
then showing an image for 3 sec or until I\E are pressed
end
This is my code; I am adding two versions, because they differ mostly in the TIMER functions and properties..
https://docs.google.com/document/d/1N6LSDAYo_DVrBCUbuPth4JPCvkI3pBNcnAZcV6Kl9wM/edit
more readable version: http://pastebin.com/vd3HNGv1
and the photos are here (although you can use any 2 photos): https://picasaweb.google.com/alex.goltser/ScrapbookPhotos
At first the problem was always an error:
you try to start the timer while it works
But now it is something else..
Why run timer functions at all?
Here's an other way how you could run your loop:
for repeat = 1:30
*show text*
drawnow %# to make sure the graphics are updated
pause(2) %# wait two seconds
*show image*
drawnow
t = tic;
done = false;
while ~done && toc(t)<3 %# checks for keypress or until 3 secs
*check for keypress*
if E/I key has been pressed
done = true;
end
end
end %# repeat 30x