Can waitforbuttonpress be used with switch cases - matlab

I have used this piece of Code but it's not working. Can you help me where I am wrong here..
for i=1:10
keydown = waitforbuttonpress;
switch keydown
case'0'
disp(5);
case'1'
disp(6);
end
end
Thank you

You are using '0' and '1', when you should use 0 and 1.
'0' - char type '0' (ASCII value of '0' equals 48. double('0') = 48).
waitforbuttonpress documentation:
k = waitforbuttonpress blocks the caller's execution stream until the function detects that the user has clicked a mouse button or pressed a key while the figure window is active. The figure that is current when you call the waitforbuttonpress function is the only area in which users can press a key or click a mouse button to resume program execution. The return argument, k, can have these values:
0 if it detects a mouse button click
1 if it detects a key press
Modify your code as follows:
for i=1:10
keydown = waitforbuttonpress;
switch keydown
case 0
disp(5);
case 1
disp(6);
end
end

Related

Matlab Psychtoolbox fprintf error with multiple keypresses within a trial

I have an experiment that collects keypresses ('x' or 'n') and reaction time in response to a stimulus display. If the participant presses either button once per trial the experiment runs fine. However, if they press the keyboard repeatedly or hold down a key, it will often crash. (I work with children and even if we ask them not to, this often will still happen).
The error that comes up when it crashes is:
Function is not defined for 'cell' inputs.
Error in Experiment (line 682)
fprintf(dataFile, formatString, SJNB, Date, Age, block, trial, trialFaceLabel, trialLoadLabel, Target, keyStroke, tStart, keyTime, Correct, RT, FaceGen);
Although it says 'Function is not defined for 'cell' inputs' (which is related to this post), this function does appear to work properly at all other times, so I can't see that it is simply not defined properly. It is only when too many keypresses have been pressed in a row (e.g. if the key has been held down), that this error occurs.
What changes can I make to ensure the experiment is robust and doesn't crash, even if there are multiple keypresses per trial? Any help would be appreciated.
I have included the code below.
Here's some additional info, in case this is helpful:
Prior to the experimental trial there is a practice loop which is set up in very much the same way but with two main differences, 1) the stimuli displayed to the screen are different and 2) the keypresses are not recorded. This loop doesn't seem to ever crash.
After crashing, the keypress responses are printed to the command line.
I have had a look at other similar posts, e.g. this post, but as far as I understand it, the keypress loop that I have written should also exit as soon as a key has been pressed - so I'm not sure why mine is not working in the same way.
The code below is all included in an experimental loop. What it's doing is:
1) searching for a keypress
2) calculating response time based on the keypress
3) beeping if the response was incorrect
4) printing to file (this is just before the end of the trial) (this is the line that the error references)
%searching for keypress
timedout = false;
pressed = 0;
%while pressed < 1;
while ~timedout && ~pressed
[keyIsDown, keyTime, keyCode] = KbCheck;
if keyIsDown && ((keyTime-tStart) < max_stimulus_shown)
keyStroke = KbName(keyCode);
if any(strcmpi(keyStroke,leftKey)) || any(strcmpi(keyStroke,rightKey)) %|| any(strcmpi(keyStroke,exitKey))
pressed = 1;
WaitSecs(remainer-(keyTime-stimulus_shown));
break;
elseif any(strcmpi(keyStroke,exitKey))
disp('*** Experiment terminated ***');
break;
sca;
end
elseif ((keyTime-tStart) > max_stimulus_shown)
keyStroke = 'None';
timedout = true;
RT = 0;
Correct = 0;
pressed = 2; % 2 = not pressed
KbQueueStop();
end
end
%calculate response times
if pressed == 1 && (~timedout)
RT = round((keyTime-tStart)*1000); % RT in ms
if any(strcmpi(keyStroke,leftKey)) % pressed left (X)
if any(strcmpi(Target, 'X')) % target was an X
Correct = 1;
else % target was X, but pressed right (N)
Correct = 0;
end
elseif any(strcmpi(keyStroke,rightKey)) % they pressed right
if any(strcmpi(Target, 'N')) % target was an N
Correct = 1;
else % target was N, but pressed right
Correct = 0;
end
elseif any(strcmpi(keyStroke,exitKey))
disp('ESC');
break;
end
end
Screen('TextSize',Screen_wid, star_size);
DrawFormattedText(Screen_wid, '.', 'center', 'center');
WaitSecs(feedback);
Screen('Flip', Screen_wid);
%say when to beep
if Correct == 0 && ~timedout
PsychPortAudio('Start', pahandle, repetitions, startCue, waitForDeviceStart);
WaitSecs(remainer-beepLengthSecs);
elseif Correct == 0 && timedout
PsychPortAudio('Start', pahandle, repetitions, startCue, waitForDeviceStart);
Screen('TextSize',Screen_wid, text_size);
DrawFormattedText(Screen_wid, 'missed trial', 'center', 'center');
Screen('Flip', Screen_wid);
WaitSecs(beepLengthSecs+feedback);
elseif Correct == 1
WaitSecs(remainer+beepLengthSecs);
end
%WaitSecs(stimulus_shown); %stimulus shown for 0.2 seconds
Screen('Flip', Screen_wid);
dataFile = fopen(dataFileName, 'a');
fprintf(dataFile, formatString, SJNB, Date, Age, block, trial, trialFaceLabel, trialLoadLabel, Target, keyStroke, tStart, keyTime, Correct, RT, FaceGen);
fclose(dataFile);
The function KbName returns the name string of key(s) input, via either a vector of key codes ( key_name = KbName([21 22]) ), or a logical vector, as returned by KbCheck.
If only only key is provided / is True, it is returned as a string. But, if more than one key is pressed at the same time, it is returned as a cell array of strings.
For example, look at the output of:
% for key name consistency across operating systems
KbName('UnifyKeyNames')
% one key
KbName(21)
ans =
r
% more than one key
KbName([21 22])
ans =
1×2 cell array
'r' 's'
Your issue is that when more than one key is pressed at the same time (with respect to the key checking loop), keyStroke is a cell array containing the keys that were pressed. You seem to be processing the cell array appropriately within most of your code, with the exception of the call to fprintf, which expects a single string, not a cell array of strings.
If you want to save a record of all keys pressed, you can convert the cell array of strings to a single string with delimiter between elements, for example by adding the following line prior to the call to fprintf:
if iscell(keyStroke)
keyStroke = strjoin(keyStroke, '_');
end
But, also keep in mind that you might want to change the logic of your experiment to reject trials in which two keys were pressed, or otherwise treat them differently than single key responses. You currently have the 'left' key taking precedence, in other words if the participant has the left key pressed and the target is an 'X', the trial will be marked correct, even if the right key is also pressed. Conversely if the participant has the left key pressed and the target is a 'N', the trial will be marked as incorrect, even if the right key is also pressed.

How to make edit text as input pushbutton as output together with a msgbox in MATLAB gui

I made a matlab gui where when user enter the value in the edit text and click on pushbutton the msgbox will popout. I tried this coding
`if value >= 1 && value <= 40
edit1String = sprintf('Your score is %f.\nYour skin is dry', value);
elseif value >= 41
edit1String = sprintf('Your score is %f.\nYour skin is moist', value);
else
rmdir('..'); %when the specifications do not say what is to happen, then the program is allowed to do ANYTHING
end`
and put it under edit text but nothing happened? I tried put it under pushbutton and nothing happen too. Anyone has any idea?

matlab's GUI KeyPressFcn

I am using the KeyPressFcn method for the edit box to test whether enter is pressed. I can use call_back but there is not event_data call_back function.
If I press one time on the button of Enter, than text doesn't rewrite, but if I double time on the button of Enter (speedly), than text rewrite.
What reasons this behaviour?
function WriteData(val, name, ind)
global solver;
switch ind
case {14, 15}
value = strcat('#(t)', val);
case 16
value = strcat('#(x)', val);
case {17, 18}
value = strcat('#(x,t)', val);
end
eval(strcat('solver.', name, ' = ', num2str(val) ) );
function edit1_KeyPressFcn(hObject, eventdata, handles)
val = get(hObject, 'String');
[~, ~, var] = GetActiveData(handles.listbox1);
ind = get(handles.listbox1, 'Value');
if (strcmp(eventdata.Key, 'return') )
WriteData(val, var, ind );
end
According to the documentation found in UIControl Properties (http://www.mathworks.com/help/matlab/ref/uicontrol-properties.html;jsessionid=49b9dc47d9f964ec95a4fe2cc9f3),
This callback function executes when the uicontrol object has focus and the user presses a key. If you do not define a function for this property, MATLAB passes key presses to the parent figure. Repeated key presses retain the focus of the uicontrol, and the function executes with each key press. If the user presses multiple keys at approximately the same time, MATLAB detects the key press for the last key pressed.
More simply put, the Callback will be called when you press enter the first time and the KeyPressFcn will be applied on the second press.

Terminating while loop with a pushbutton Matlab

I have a uitable and a function that returns the id of the item once the user clicks on its respective row. The id is also a global variable, as it is used over various functions.
The idea is that I create an array with all the user chosen items from the uitable, terminated when save playlist is clicked. Ex. if the user chooses items with id's 5, 7, 9 in succession and then clicks the 'save playlist' button, I want the array to hold
5 7 9
I thought that the best way to do this is using a while loop. The while loop should check if the save button has been clicked. I have a global variable that changes once the program goes into the 'save playlist' button callback function.
The problem is that once the user chooses an ID, the array keeps on iterating until the user chooses another ID, and will keep on iterating etc etc until the save button is clicked. Ex: the user clicks on ID 5, the array will record 55555555555555... recurring until user clicks on ex. ID 7: 555555555555557777777777, since the program keeps on looping and looping without pausing.
The code looks like this:
while (keeprunning)
idvec = [idvec id];
end
keeprunning is a global variable and is initialized with a value of 1 in the opening function. It is changed to 0 in the 'save playlist' callback function.
I thought to fix this problem by introducing a new global variable call it 'itemselected' that initializes in the opening function as 1 and changes to 1 again everytime the cell selection callback is called. After an ID is added to the array in the while loop, this variable resets to 0.
The idea is that the loop should iterate while the 'save playlist' button is not clicked (controlled by the keeprunning global variable) BUT the program should not let the while loop iterate until the user clicks on another row i.e. until the cell selection call back function is called again.
I need something like this but this doesn't work (infinite loop). Or else some other suggestion??
while (keeprunning || trackselected)
idvec = [idvec id];
trackselected = 0;
end
Thank you in advance
To record a history of the user selecting fields inside a uitable, do something like this:
function tbl_example
% Create the figure
fh = figure('Visible', 'off')
ud.selected_list = [];
d = gallery('integerdata',100,[10 3],0);
t = uitable(fh,'Data',d,'ColumnWidth',{50}, 'cellselectioncallback', #cell_history );
set( fh, 'visible', 'on' );
set( fh, 'userdata', ud );
return
function cell_history( h, event_data )
fh = get( h, 'Parent' )
ud = get( fh, 'userdata' );
indx = event_data.Indices;
ud.selected_list = [ ud.selected_list h.Data( indx(1), indx(2) ) ]
set( fh, 'userdata', ud );
return
Then, when you hit your "playlist" button, just read the userdata field in the parent figure handle.
I fixed this problem after stopping from thinking about it and doing something else; fascinatingly it came to me as a very simple method.
What I did was create a global array in the CellSelectionCallback. The program checks whether the program was initiated to create a playlist through the use of a boolean variable in the 'create a playlist' button callback, and in this case the global array is appended with the chosen row's item's id. Since the array is global it can be used over different functions. The array is flushed after 'save playlist' button is clicked.
It was as simple as that, however, sometimes simple is not that simple, especially after about 10 hours of seeing matlab code.

MATLAB GUI Button with Keyboard Control

I have a button in a GUI. which the user presses to execute a Callback. But, I would like the user to be able to press the up arrow key instead of clicking to execute the callback.
EDIT: I am using GUIDE to make the GUI
Check out this thread:
http://www.mathworks.com/matlabcentral/answers/12034
Just slightly modifying the code from there to here (put the following in a file called testGUI.m
function testGUI
g = figure('KeyPressFcn', #keyPress)
MyButton = uicontrol('Style', 'pushbutton','Callback',#task);
function task(src, e)
disp('button press');
end
function keyPress(src, e)
switch e.Key
case 'uparrow'
task(MyButton, []);
end
end
end