user001
user001

Reputation: 1848

matlab KeyPressFcn for holding a key

I would like to allow the user to zoom only while the control key is held (depressed). I have implemented this as follows within a WindowKeyPressFcn callback function:

function keypress_callback(obj, evd, hZoom)
switch evd.Key
  case 'control'
    set(hZoom,'Enable','on');
end
%disp(evd); % used for debugging purposes

This function accepts a zoom object handle (hZoom) that is passed from the main program at the moment the callback function is activated (set(hFigure,'WindowKeyPressFcn',{@keypress_callback,hZoom});). I have written a similar WindowKeyReleaseFcn (set via set(hFigure,'WindowKeyReleaseFcn',{@keyrelease_callback,hZoom});) to disable zooming when control is released.

function keyrelease_callback(obj, evd, hZoom)
switch evd.Key
  case 'control'
    set(hZoom,'Enable','off');
end
%disp(evd); % used for debugging purposes

The goal is to allow normal zooming behavior (click to zoom in by a factor; shift-click to zoom out by a factor; drag clicking to zoom in on a selected region) only while the Ctrl key is depressed. As soon as this modifier key is released, zooming ability should be disabled.

However, this behavior does not work as intended. Simply testing (by disp(evd)) whether a key is pressed reveals that any number of key presses can be made with arbitrary keys; however, if the pressed key is Ctrl, only one such press can be made, and all subsequent presses of Ctrl are ignored, while all subsequent presses of any other key cause the key to appear in the Matab command window instead of triggering the keypress_callback function. Thus, pressing Ctrl appears to somehow inactivate the keypress_callback function, perhaps because focus is shifted from the figure to the zoom object? As a corollary question, the WindowKeyReleaseFcn seems to work fine for non-modifier keys (the evd shows the correct released key), but the key in evd is empty if the released key is a non-modifier key.

I would be grateful if someone could demonstrate the correct implementation of the control-dependent zoom behavior as envisaged.

Upvotes: 4

Views: 2259

Answers (1)

jez
jez

Reputation: 15369

The more modern way to do things seems to be:

gca
zoom on
z = zoom(gcf);
set(z, 'ButtonDownFilter', @ZoomGate)

where ZoomGate.m contains something like:

function inhibitZoom = ZoomGate(varargin)

if ismember('control', get(gcbo,'currentModifier'))
    inhibitZoom = 0;
else
    inhibitZoom = 1;
end

EDIT in response to questioner's comments:

My first suggestion was to use a WindowButtonDownFcn callback which then calls zoom itself if it detects the control modifier. This is fine provided you have control over the zoom implementation. Looking back at my code (I did something like this anything up to 15 years ago) I find that it used to be simple — zoom was an m-file and had an obvious way of calling it: zoom down meant "the button has just been pressed". Then, in that way that they do, MathWorks moved the goal posts and changed zoom. It looks like my response at the time was to re-implement my own zoom in the older, simpler style. Doesn't help you, unless you actually want that code (let me know).

Upvotes: 1

Related Questions