Hello,
I am creating a questionnaire using the programmatic GUI, but I would like participants to use the numbers on the keyboard to respond instead of a mouse. In the questionnaire, participants would select the appropriate radio button by pressing the corresponding numbers on the keyboard and to lock in their responses, they press the spacebar. This would then bring them to the next question, and so on.
To do this, I used the WindowsKeyPressedFcn to check which key was pressed, and then call a callback function depending on which element was visible. My key pressed callback function looks like this
function keyPressCallback(source,eventdata) % determine the key that was pressed
keyPressed = eventdata.Key; if strcmpi(keyPressed,'space') if strcmp(get(Next1, 'Visible'), 'on') == 1 % the key that was pressed was the space bar so set focus to
% the Next button
uicontrol(Next1); % invoke the callback for the Next button
Next1_callback(Next1,[]); elseif strcmp(get(Next2, 'Visible'), 'on') == 1 uicontrol(Next2); Next2_callback(Next2, []); elseif strcmp(get(Next3, 'Visible'), 'on') == 1 uicontrol(Next3); Next3_callback(Next3, []); elseif strcmp(get(Next4, 'Visible'), 'on') == 1 uicontrol(Next4); Next4_callback(Next4, []); elseif strcmp(get(CompNext, 'Visible'), 'on') == 1 uicontrol(CompNext); CompNext_callback(CompNext, []); elseif strcmp(get(RRStart, 'Visible'), 'on') == 1 uicontrol(RRStart); RRStart_callback(RRStart, []); elseif strcmp(get(RRNext, 'Visible'), 'on') == 1 uicontrol(RRNext); RRNext_callback(RRNext, []); end end if strcmpi(keyPressed, '1') || strcmpi(keyPressed, '2') || strcmpi(keyPressed, '3') || strcmpi(keyPressed, '4') || strcmpi(keyPressed, '5') || strcmpi(keyPressed, '6') || strcmpi(keyPressed, '7') guidata(handles.Questionnaire, keyPressed); if strcmp(get(curr_feel_ans, 'Visible'), 'on') == 1 uicontrol(curr_feel_ans); feel_callback(curr_feel_ans, []); elseif strcmp(get(Motiv_ans, 'Visible'), 'on') == 1 uicontrol(Motiv_ans); Motiv_callback(Motiv_ans, []); elseif strcmp(get(MC_ans, 'Visible'), 'on') == 1 uicontrol(MC_ans); MC_callback(MC_ans, []); elseif strcmp(get(Comp_ans, 'Visible'), 'on') == 1 uicontrol(Comp_ans); Comp_callback(Comp_ans, []); elseif strcmp(get(RR_ans, 'Visible'), 'on') == 1 uicontrol(RR_ans); RR_callback(RR_ans, []); end end clear keyPressed end
The buttons here are listed in the order in which the questions appear. This works until I get to the RRStart. RRStart is a Next button that appears below some instructions to participants on how to answer the next few questions. After participants read the instructions, they have to press the spacebar to proceed to the actual questions. At this point, the program seems to freeze, and pressing the spacebar does nothing. However, if I minimize the window and maximize it again, pressing the spacebar brings me to the first question. When I'm on the first question, pressing one of the response numbers does nothing until I once again minimize and maximize the window. After this, the questionnaire seems to work properly again. For reference, here is code for this set of questions including the instructions
handles.REW_QNS.Reward_responsiveness = [];RR_idx = 1;handles.Questionnaire = figure('Name', 'Questionnaire', 'Color', [.8 .8 .8], 'NumberTitle', 'off', 'OuterPosition',[0 0 1920 1200],'Units','Pixels');space_start = uicontrol('Visible', 'on', 'Style','Text', 'BackgroundColor', [.8 .8 .8], 'ForegroundColor', [0 0 0], 'FontSize', 14, 'FontUnits', 'points', 'Position',[650 600 640 70],'String','Press the spacebar to start');RR_instruct = uicontrol('Visible', 'on', 'Parent', handles.Questionnaire, 'Style','Text', 'BackgroundColor', [.8 .8 .8], 'ForegroundColor', [0 0 0], 'FontSize', 14, 'FontUnits', 'points', 'Position',[650 700 640 70],'String','For the following 8 items, please indicate to what extent you agree with each statement by pressing the corresponding number on the keyboard.');RR_ans = uibuttongroup('Visible', 'off', 'BackgroundColor', [.8 .8 .8]);RRans1 = uicontrol('Style', 'radiobutton', 'Parent', RR_ans, 'FontSize', 12, 'FontUnits', 'points', 'BackgroundColor', [.8 .8 .8], 'Position', [600 660 200 50], 'String', '1. Strongly disagree', 'HandleVisibility', 'off', 'Tag', '1');RRans2 = uicontrol('Style', 'radiobutton', 'Parent', RR_ans, 'FontSize', 12, 'FontUnits', 'points', 'BackgroundColor', [.8 .8 .8], 'Position', [795 660 200 50], 'String', '2. Somewhat disagree', 'HandleVisibility', 'off', 'Tag', '2');RRans3 = uicontrol('Style', 'radiobutton', 'Parent', RR_ans, 'FontSize', 12, 'FontUnits', 'points', 'BackgroundColor', [.8 .8 .8], 'Position', [1005 660 200 50], 'String', '3. Somewhat agree', 'HandleVisibility', 'off', 'Tag', '3');RRans4 = uicontrol('Style', 'radiobutton', 'Parent', RR_ans, 'FontSize', 12, 'FontUnits', 'points', 'BackgroundColor', [.8 .8 .8], 'Position', [1200 660 200 50], 'String', '4. Strongly agree', 'HandleVisibility', 'off', 'Tag', '4');set(RR_ans, 'SelectionChangeFcn', @RR_callback);set(RR_ans, 'SelectedObject', []);RR(1) = uicontrol('Visible', 'off', 'Parent', RR_ans, 'Style', 'Text', 'BackgroundColor', [.8 .8 .8], 'ForegroundColor', [0 0 0], 'FontSize', 14, 'FontUnits', 'points', 'Position',[605 800 700 48],'String','I am someone who goes all-out.');RR(2) = uicontrol('Visible', 'off', 'Parent', RR_ans, 'Style', 'Text', 'BackgroundColor', [.8 .8 .8], 'ForegroundColor', [0 0 0], 'FontSize', 14, 'FontUnits', 'points', 'Position',[600 800 700 48],'String','If I discover something new I like, I usually continue doing it for a while.');RR(3) = uicontrol('Visible', 'off', 'Parent', RR_ans, 'Style', 'Text', 'BackgroundColor', [.8 .8 .8], 'ForegroundColor', [0 0 0], 'FontSize', 14, 'FontUnits', 'points', 'Position',[605 800 700 48],'String','I would do anything to achieve my goals.');RR(4) = uicontrol('Visible', 'off', 'Parent', RR_ans, 'Style', 'Text', 'BackgroundColor', [.8 .8 .8], 'ForegroundColor', [0 0 0], 'FontSize', 14, 'FontUnits', 'points', 'Position',[610 800 700 48],'String','When I am successful at something, I continue doing it.');RR(5) = uicontrol('Visible', 'off', 'Parent', RR_ans, 'Style', 'Text', 'BackgroundColor', [.8 .8 .8], 'ForegroundColor', [0 0 0], 'FontSize', 14, 'FontUnits', 'points', 'Position',[610 800 700 48],'String','When I go after something I use a “no holds barred” approach.');RR(6) = uicontrol('Visible', 'off', 'Parent', RR_ans, 'Style', 'Text', 'BackgroundColor', [.8 .8 .8], 'ForegroundColor', [0 0 0], 'FontSize', 14, 'FontUnits', 'points', 'Position',[600 800 700 48],'String','When I see an opportunity for something I like, I get excited right away.');RR(7) = uicontrol('Visible', 'off', 'Parent', RR_ans, 'Style', 'Text', 'BackgroundColor', [.8 .8 .8], 'ForegroundColor', [0 0 0], 'FontSize', 14, 'FontUnits', 'points', 'Position',[600 800 700 48],'String','When I am doing well at something, I love to keep at it.');RR(8) = uicontrol('Visible', 'off', 'Parent', RR_ans, 'Style', 'Text', 'BackgroundColor', [.8 .8 .8], 'ForegroundColor', [0 0 0], 'FontSize', 14, 'FontUnits', 'points', 'Position',[600 800 700 48],'String','If I see a chance to get something I want, I move on it right away.');RRStart = uicontrol('Parent',handles.Questionnaire,'Visible', 'on', 'Style','pushbutton', 'Position',[0.1 0.1 1 1], 'Callback',{@RRStart_callback});RRNext = uicontrol('Parent',handles.Questionnaire,'Visible', 'off', 'Style','pushbutton', 'Position',[0.1 0.1 1 1], 'Callback',{@RRNext_callback});handles.temp_data = 0;set(handles.Questionnaire,'WindowKeyPressFcn',@keyPressCallback); function keyPressCallback(source,eventdata) keyPressed = eventdata.Key; if strcmpi(keyPressed,'space') if strcmp(get(RRStart, 'Visible'), 'on') == 1 uicontrol(RRStart); RRStart_callback(RRStart, []); elseif strcmp(get(RRNext, 'Visible'), 'on') == 1 uicontrol(RRNext); RRNext_callback(RRNext, []); end end if strcmpi(keyPressed, '1') || strcmpi(keyPressed, '2') || strcmpi(keyPressed, '3') || strcmpi(keyPressed, '4') || strcmpi(keyPressed, '5') || strcmpi(keyPressed, '6') || strcmpi(keyPressed, '7') guidata(handles.Questionnaire, keyPressed); if strcmp(get(RR_ans, 'Visible'), 'on') == 1 uicontrol(RR_ans); RR_callback(RR_ans, []); end end end function RRStart_callback(~,~) set(RR_instruct, 'Visible', 'off'); set(space_start, 'Visible', 'off'); set(RRStart, 'Visible', 'off'); set(RR(1), 'Visible', 'on'); set(RRNext, 'Visible', 'on'); set(RR_ans, 'Visible', 'on'); end function RR_callback(~,~) handles.temp_data = str2num(guidata(handles.Questionnaire)); if handles.temp_data == 1 set(RR_ans, 'SelectedObject', RRans1); elseif handles.temp_data == 2 set(RR_ans, 'SelectedObject', RRans2); elseif handles.temp_data == 3 set(RR_ans, 'SelectedObject', RRans3); elseif handles.temp_data == 4 set(RR_ans, 'SelectedObject', RRans4); end guidata(handles.Questionnaire, handles.temp_data); end function RRNext_callback(~,~) if (handles.temp_data ~= 0) && (handles.temp_data < 5) handles.REW_QNS.Reward_responsiveness(RR_idx) = handles.temp_data; set(RR_ans, 'SelectedObject', []); set(RR(RR_idx), 'Visible', 'off'); RR_idx = RR_idx + 1; if RR_idx <= 8 set(RR(RR_idx), 'Visible', 'on'); else set(RRNext, 'Visible', 'off'); set(RR_ans, 'Visible', 'off'); end end handles.temp_data = 0; end
Running this questionnaire on its own (without the questions that come before this) works properly. The problem seems to be that when more questions are added, Matlab slows down. Am I correct in thinking this? Or is something else the problem here? If I am right and my main function is too big (all my callbacks are nested within the main function), how can I prevent the program from lagging? Should I split my callback functions into separate .m files and call them within my main function? Thank you in advance!
Best Answer