for i=1:100
fid=loadfigure(fnames(i).name)
pause(5)
end
The pause function is added to check figure. How to save iteration number (in fact, the file number) upon key press.
Use timer instead of pause with Java Robot. Use input for key presses in the command window.
input returns an empty matrix if Enter is pressed before pressing anything else. The below code waits for the user input for 5 seconds and if the user doesn't input anything, the Java Robot will press Enter and the code proceeds to the next iteration. If the input function returns something then it saves the iteration number before proceeding to the next iteration.
t = timer('StartDelay', 5, 'TimerFcn', #PressEnterButton);
ind=1;
for k=1:100
fid=loadfigure(fnames(i).name); %as it is from your code
start(t); %start the 5sec timer
if ~isempty(input('Wait for button press','s'));
iterNum{ind}= k; ind=ind+1;
end
stop(t); %stop the timer object
end
delete(t); %delete the timer object
function PressEnterButton(HObj, event)
%Function to press Enter button
import java.awt.*;
import java.awt.event.*;
r=Robot;
r.keyPress(KeyEvent.VK_ENTER);
r.keyRelease(KeyEvent.VK_ENTER);
end
P.S: The above code saves the iteration number when alphanumeric and/or special character keys are pressed.
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 have a slider and a edit field, which are defined as
uicontrol(fig,'Style','Slider','Units','characters','Position',[17.1+f*iwidth 10.5 4 28.6],'Min',0,'Max',1000,'Value',500,'SliderStep', [1/500 , 10/500 ],'Callback','evaluation_callbacks(''results'',guidata(gcbo))','Tag',['slider' int2str(f)]);
uicontrol(fig,'Style','Edit','Enable','inactive','Units','characters','Position',[14+f*iwidth 8.2 9 1.6],'FontSize',10,'String',500,'Tag',['rating' int2str(f)]);
With the following Callback functions:
function evaluation_callbacks(varargin)
% EVALUATION_CALLBACKS Callback functions for the evaluation interface
%
% evaluation_callbacks(fname,varargin) executes the callback function
% fname_callback with various parameters
fname=[varargin{1},'_callback'];
feval(fname,varargin{2:end});
%%%saving the rating results and proceeding to the next experiment or exiting
function results_callback(handles)
% stop audio
clear sound
%getting the ratings for all files
for f=1:handles.nbfile
handles.ratings(handles.expe_order(handles.expe),handles.file_order(f))=get(getfield(handles,['slider' int2str(f)]),'Value');
end
%saving the whole results (to avoid losing data if the program terminates early)
results='';
fid=fopen(handles.resultfile,'w');
for e=1:handles.nbexpe
for f=1:handles.nbfile
fprintf(fid,'%d\n',handles.ratings(e,f));
end
end
fclose(fid);
if handles.expe<handles.nbexpe
handles.expe=handles.expe+1;
% updating title
set(handles.experiment,'String',handles.parameter{handles.expe});
% update evaluation parameters
set(handles.scale90,'String',handles.high{handles.expe});
set(handles.scale10,'String',handles.low{handles.expe});
if handles.expe==handles.nbexpe
pos=get(handles.results,'Position');
pos(1)=pos(1)+2.5;
pos(3)=19;
set(handles.results,'Position',pos,'String','Save and exit');
end
%moving all the sliders back to 50
for f=1:handles.nbfile
shandle=getfield(handles,['slider' int2str(f)]);
set(shandle,'Value',500);
rhandle=getfield(handles,['rating' int2str(f)]);
set(rhandle,'String',500);
end
%randomizing the order of the tested files for the next experiment
handles.file_order=randperm(handles.nbfile);
%testing whether a break is needed before the next experiment
if etime(clock,handles.time) > 20*60
wfig=warndlg(['You have been working for ' int2str(round(etime(clock,handles.time)/60)) 'minutes. It is recommended that you take a break of at least the same duration before starting the next experiment. Click on OK when you are ready.'],'Warning');
uiwait(wfig);
end
handles.time=clock;
% Start next audio sample
play_callback(handles,1)
guidata(gcbf,handles);
else
%exiting
close(gcbf);
end
%%%rounding and displaying the values of the sliders
function slider_callback(handles,f)
shandle=getfield(handles,['slider' int2str(f)]);
set(shandle,'Value',round(get(shandle,'Value')));
rhandle=getfield(handles,['rating' int2str(f)]);
set(rhandle,'String',get(shandle,'Value'));
As it is right now, the edit field value are not live updated if. The value of the edit field are only updated if the slider is moved and the mouse button is released.
I have tried to add a listener to the slider, but I cannot make it work. So far I have followed the following guides/posts without any luck.
http://undocumentedmatlab.com/blog/continuous-slider-callback
and
https://se.mathworks.com/matlabcentral/answers/140706-use-slider-for-live-updating-of-threshold-on-2d-contour-plot
Can anybody help?
Add a listener in the myGUI_OpeningFcn. Note you need to change myGUI to match your GUI script filename.
addlistener(handles.slider1,'ContinuousValueChange',#(hObject,eventdata)myGUI('updateText',hObject,eventdata,guidata(hObject)));
Then, add the following function in your GUI script.
function updateText(hObject, eventdata, handles)
set(handles.text2,'String',get(hObject,'Value'));
guidata(hObject,handles);
More specifically, in your case, you need to add a bunch of listeners:
for i=1:handles.nbfile
addlistener(getfield(handles,['slider' int2str(i)]),'ContinuousValueChange',#(hObject,eventdata)myGUI('updateText',hObject,eventdata,guidata(hObject)));
end
Then add:
function updateText(hObject, eventdata, handles)
f = hObject.Tag(7:end);
set(getfield(handles,['rating' f]),'String',get(hObject,'Value'));
guidata(hObject,handles);
Update
In your GUI script, add listeners in the OpeningFcn (which is the second function automatically generated by Matlab when your GUI was created):
for i=1:handles.nbfile
addlistener(getfield(handles,['slider' int2str(i)]),'ContinuousValueChange',#(hObject,eventdata)myCallBackFileName('updateText',hObject,eventdata,guidata(hObject)));
You will need to change myCallBackFileName to match the filename of your callback script. Then add the updateText function.
I have a function that displays a graph with some random elements. I want to have it so that when the user presses a certain key the function runs again, redistributing these random elements on the graph. What is the best way to go about doing this?
You can wrap this within a while loop and using ginput. Put your function call within a while loop, use ginput and poll for a keystroke, and while this key is being pushed, keep going. Something like this, assuming that your figure is open after each call to the function:
while true
%// Generate random data
%// Call function
%// Open figure
%// Get a key from the user
[~,~,b] = ginput(1);
%// If you push C or c, then continue
if b == 67 || b == 99
continue;
else %// Else, get out
break;
end
end
You want to set a key press callback for a figure you're using in a script by using the KeyPressFcn like so:
h = figure('KeyPressFcn',#testcallback);
Then place the following in a function testcallback.m file (you can also use a function handle):
function testcallback(hObject,callbackdata)
% Check to make sure key pressed is the escape key
if (strcmp(callbackdata.Key,'escape'))
% Do whatever processing you want
imshow(rand(40));
end
end
When you run the script, a figure will appear. Everytime you press escape, the function will fire:
using the input() function in MATLAB allows you to prompt and ask a user for input. You can use this function to prompt the user to enter a key, when this key is entered, your function can be called and re-run.
Documentation on this can be found on the Mathworks website
I have the following code in MATLAB, where the user has to enter the word "precipitations" letter by letter. After typing one letter, the user has to press Enter and the program checks, whether the typed letter was correct.
Now I would like to change the program, such that the user does not have to press Enter after typing a letter. Is there any operator or function in MATLAB which reacts to every pushed button, so one does not have to press Enter?
disp('Please enter "precipitations" without errors')
target=('precipitations');
n=size(target); n=n(2); % Characters number
for i=1:n;
YourInput(i)=input('','s');
if YourInput(i)==target(i)
disp('OK. Please, input the next symbol')
i=i+1;
else
disp('Error. Please try again.')
break
end
end
As far as I know, there is no built-in MATLAB function to do this. There is however a function getkey on MATLAB File Exchange.
You can download this function and change your code to use
YourInput(i) = getkey();
--
I of course wondered how this can be achieved, and it does the following: They create a new figure with a window size of 0,0 at position (1,1). You'll notice the new figure at the bottom left of the screen.
Then, a callback function KeypressFcn which is executed whenever a key is pressed, is created. The pressed key is saved in the UserData field of the figure, and returned as variable. The interesting parts of the function (and a minimal example) are:
fh = figure(...
'keypressfcn','set(gcbf,''Userdata'',double(get(gcbf,''Currentcharacter''))) ; uiresume ', ...
'position',[0 0 1 1] ...
);
uiwait ;
key = get(fh,'Userdata') ;
delete(fh) ;
EDIT: I rephrased my question a bit, because I have a better understanding of the problem now and there was a lot of unnecessary info in the first draft.
I am creating a standalone MATLAB application, which needs a toggle button that can initiate and stop a looping script.
Based on this helpful video, I was able to implement this idea like this in my gui.m file:
function startBtn_Callback(hObject, eventdata, handles)
if get(handles.startBtn,'Value')
set(handles.startBtn,'String','Stop Recording');
else
set(handles.startBtn,'String','Start Recording');
end
while get(handles.startBtn,'Value');
disp('looping..');
pause(.5);
end
This script works as expected, but when I replace the contents of the while loop the function I would like to loop, the button stops working. It still toggles when I push it, but the callback only gets called the first time the button is pushed. Here is what my final code looks like:
function startBtn_Callback(hObject, eventdata, handles)
if get(handles.startBtn,'Value')
set(handles.startBtn,'String','Stop Recording');
pause(.1);
else
set(handles.startBtn,'String','Start Recording');
disp('Recording Stopped')
end
while get(handles.startBtn,'Value');
myFunction();
end
When I push the start button, this callback runs and the loop starts. The pause(.1) is needed to get the text to change - if I don't include a pause, the loop initiates, but the text on the button does not change.
After this, no subsequent button pushes do anything. The button toggles on the GUI, but startBtn_Callback never gets called and the loop runs indefinitely. This is a problem because my end user will not have access to the MATLAB console.
To give a bit more information about my function: its a method that records audio for 5 seconds, does some processing, then outputs some graphs. I want this loop to repeat indefinitely until the user pushes stop.
I think that the issue is that MATLAB seems to only be able to run one function at a time, so when myFunction() is running, the callback can't be initiated. The reason it worked in the first example is because there was a pause between loop calls. I can't have this pause, because a requirement of the project is to record every possible second.
How can I make a reliable stop button for this process?
I am running MATLAB R2012b 32-bit.
In your code snippet
a=get(handles.startBtn,'Value')
while a
myFunction();
end
the value of a is assigned once, and never changes afterward. Thus, the while-loop will either never run, or it will loop forever.
while get(handles.startBtn,'Value')
myFunction();
end
will query the value of the button at every iteration, however, especially if myFunction doesn't take very long to execute, there will be lots and lots of java requests that may make your GUI sluggish.
This is why the example you followed uses the pause line, so that the loop only executes every .5 seconds or so.
If you don't want to have the query in the while-line, you can alternatively write
%# read inital value of a
a=get(handles.startBtn,'Value');
while a
myFunction();
%# update a
a=get(handles.startBtn,'Value');
end
drawnow() is the function I was looking for. Putting that after myFunction() forces Matlab to handle any stacked up GUI calls before proceeding with the loop.
This code creates a reliable start/stop toggle button for an indefinite and continuous process:
function startBtn_Callback(hObject, eventdata, handles)
if get(handles.startBtn,'Value')
set(handles.startBtn,'String','Stop');
drawnow();
else
set(handles.startBtn,'String','Start');
end
while get(handles.startBtn,'Value');
myFunction();
drawnow()
end