if <key> is pressed, move <some plotted function> to the right/left
37 views (last 30 days)
here is the code: (the function 'catchkeypress' is below)
save('testp','xkey'); %saves 'xkey'
load('testp','xkey'); %force script to update the variable 'xkey'
catchKeyPress() %my function
and the required function:
load('testp','xkey'); %load 'xkey' into function
function KeyPressCb(~,evnt) %?not sure how this works?
if strcmpi(evnt.Key,'leftarrow') %left-arrow is pressed
xkey=xkey-0.01; %decrease 'xkey'
elseif strcmpi(evnt.Key,'rightarrow') %right-arrow is pressed
xkey=xkey+0.01; %increase 'xkey'
this code 'works' (y=x.^2 moves to the right if I press the right arrow on my keyboard),
but I think there is a better way of doing so.
Also, it ONLY works for one variable, 'xkey' in my case, and..
... I can't control how 'much' the figure moves per time I press a button;
... (appearently) I 'have' to save&load the variable 'xkey' in both the script and function for it to work.
What I'm hoping for is something like this:
for i=1:n %OR while condition
in other words, I want to be able to pass the following to 'my' function:
- wich variable I want to change if I press a key on my keyboard;
- how much it changes if I press it once
and get the 'updated' value as output.
I hope I explained my problem properly, and any help is welcome
Nirav Sharda on 13 Jun 2017
This can be achieved using guidata function which allows to share data between the GUI and callbacks. I have created a small script that you can use as a reference.
% Creating the intial figure data
offset = 0;
f = figure;
% Using guihandles to create the structure in which data can be saved
myhandles = guihandles(f);
% Adding an offset field to the structure
myhandles.offset = 0;
% Save the structure
% Set the KeyPressFcn Callback
% Get the structure using guidata in the callback
myhandles = guidata(src);
% If right arrow is pressed
%Modify offset in the strucuture with the rate you want
myhandles.offset = myhandles.offset + rate;
% Save the change to the structure
% Get the line object which is the grand-child of the figure
lineObject = src.Children.Children;
% Modify the YData of the line object.
x = lineObject.XData;
lineObject.YData = (x-myhandles.offset).^2;
I have also used the 'KeyPressFcn' callback on the figure window. I hope this helps.
Arnav Mendiratta on 13 Jun 2017
In addition to above answer, you may also achieve this without the use of guidata. The following code updates the frequency of plotted sine wave based on key press.
E.g. Initially, the frequency has been set as 10. If you run the script and press 2, you'll see the frequency of new sine wave to be 20. If you press 9, the new frequency becomes 90.
This is a reference code, I have not implemented any error handling. For example, if you press a character, the frequency becomes 0 and the sine wave disappears.
% set the data for plotting
Fs=1000; %sample rate
dt = 0:1/Fs:1; %time vector
f = 10; %signal frequency
y = sin(2*pi*f*dt); %final signal
% plot the figure and get the figure handle
hFig = figure('KeyPressFcn', @changeFreqOnKeyPress);
hAxs = plot(dt,y);
getKey = src.CurrentCharacter;
newFreqMultiplier = str2double(getKey);
newFreq = newFreqMultiplier*10
src.Children.Children.YData = sin(2*pi*newFreq*src.Children.Children.XData);
Steven Lord on 13 Jun 2017
What's your goal? Is it to see parts of the function to the right or left of the current "view" in the axes? If so, consider panning your axes instead of using a file-based system for sharing data between callbacks (there are other techniques that will likely work better and/or faster for you) and replotting your data.