How to Have Matlab Continually Detect Keystrokes Without Interupting Program Execution

Passing variable around:

I recommend using setappdata and getappdata to pass variables around between callbacks of a GUI.
You can also read Share Data Among Callbacks for more informations about this aspect.

Assigning and disabling callbacks:

To disable a callback function, you do not need to re-assign the callback to a function that does nothing, you can simply assign an empty array:

          % assign the 'KeyDownListener' function and pass one parameter ('var1') with it set( h.fig, 'KeyPressFcn',{@KeyDownListener,var1})   % then later when you don't need it anymore: % Disable the 'KeyPressFcn listener, assign 'empty' to it set( h.fig, 'KeyPressFcn',[])                  

Full example:

Below is a minimal GUI which demonstrate how to capture a single key press (and the time), then save the data collected into the appdata space of the application, where they are collected again by a 'display' function (where you could also do whatever you want with the data collected).

code for SingleKeyPressDemo.m:

          function h = SingleKeyPressDemo  % create a minimal figure with a button and 2 text fields h.fig = figure ; h.btn = uicontrol('Style','Pushbutton','String','Start capture',...                   'units','Normalized','Position',[0.1 0.6 0.8 0.3],...                   'Callback',@StartKeyCapture) ; h.txtKey = uicontrol('Style','text','String','Key pressed:',...                   'units','Normalized','Position',[0.1 0.4 0.8 0.1]) ; h.txtTime = uicontrol('Style','text','String','Elapsed time:',...                   'units','Normalized','Position',[0.1 0.3 0.8 0.1]) ;  % assign a callback to the KeyRelease event to intercept passing the % eventdata to the command window set(h.fig,'KeyReleaseFcn',@KeyReleased)  % initialise appdata variables to hold the captured key and the time setappdata( h.fig , 'CapturedKey' , [] ) setappdata( h.fig , 'Elapsed_time' , [] )  % save the handle structure guidata( h.fig , h)   function StartKeyCapture(hobj,~)     h = guidata( hobj ) ;   % retrieve the handle structure     StartTime = tic ;       % Start a stopwatch      % assigne the callback funtion, passing the stopwatch in parameter     set(h.fig,'KeyPressFcn',{@KeyDownListener,StartTime})      % disable the button until a key is pressed (also makes it loose the     % focus, which is handy otherwise the button keeps the focus and hides     % the 'KeyPressedFcn'     set( h.btn , 'Enable','off')   function KeyDownListener(hobj, key_obj, starting_time)     % Detect key pressed and time elapsed     Elapsed_time = toc(starting_time) ;     key_pressed = key_obj.Key;      h = guidata( hobj ) ;                                   % retrieve the handle structure     setappdata( h.fig , 'CapturedKey' , key_pressed ) ;     % save the captured key     setappdata( h.fig , 'Elapsed_time' , Elapsed_time ) ;   % save the elapsed time       set(h.fig,'KeyPressFcn',[]) % remove listener so new key press will not trigger execution     set( h.btn , 'Enable','on') % re-enable the button for a new experiment      % (optional) do something after a key was pressed     display_results(h.fig) ;   function display_results(hobj)     h = guidata( hobj ) ;   % retrieve the handle structure      % retrieve the saved data     CapturedKey  = getappdata( h.fig , 'CapturedKey' ) ;     Elapsed_time = getappdata( h.fig , 'Elapsed_time' ) ;      % update display     set( h.txtKey  , 'String', sprintf('Key pressed: %s',CapturedKey) ) ;     set( h.txtTime , 'String', sprintf('Elapsed time: %f ms',Elapsed_time) ) ;  function  KeyReleased(~,~) % do nothing % The only purpose of this function is to intercept the KeyReleased event % so it won't be automatically passed on to the command window.                  

Creating GUI programmatically is full of verbose in Matlab, focus on the code in the 2 functions StartKeyCapture and KeyDownListener to achieve what you were asking.

This example will produce the following GUI:

enter image description here


Additional note:

I would also recommend against the use of gcf in a GUI application. It is a handy shortcut when debugging or working in the console with figures opened around, but in a GUI the calls to its own elements should be as self-contained as possible. MATLAB offers way to save the handles of all your GUI elements (all the uicontrols, including the main figure), so you can call them explicitely when you need them. This reduces the risk of errors (imagine your user is also running other figures in the same MATLAB session, if your callback triggers and call gcf when the user was fiddling with another figure, you are going to try to execute code on a different figure than it was intended to ... which can easily result in errors).

Read the documentation on guidata for more information (and/or observe how I've used it in the example above).


Edit:

To avoid the focus coming back to the command window at every key pressed, you also have to also define a callback function to the corresponding KeyRelease event, otherwise the event will automatically be forwarded to the command window (which will take the focus).

A clean way to do is to simply add callback assignment

          set(h.fig,'KeyReleaseFcn',@KeyReleased)                  

once and for all in the figure definition (you don't have to set/undo this callback at each experiment), and then define an empty function function KeyReleased(~,~) which does nothing. This way is implemented in the modified code example above.

Another way to do without the extra empty function, would be to simply define the callback in line at the assignment time:

          set(h.fig,'KeyReleaseFcn','disp([])')                  

This way you do not need to have an empty KeyReleased function.

Note however that a callback function must be defined (either inline or later in the code). Simply assigning empty to the callback will not work. (e.g. both options below will fail to intercept the event and will forward it to the command window:

          set(h.fig,'KeyReleaseFcn','') % not working set(h.fig,'KeyReleaseFcn',[]) % not working either                  

cherryabliand41.blogspot.com

Source: https://stackoverflow.com/questions/38628195/make-matlab-accept-keypress-only-once

0 Response to "How to Have Matlab Continually Detect Keystrokes Without Interupting Program Execution"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel