if <key> is pressed, move <some plotted function> to the right/left

14 Ansichten (letzte 30 Tage)
Luc Bleijenberg
Luc Bleijenberg am 3 Jun. 2017
Beantwortet: Steven Lord am 13 Jun. 2017
here is the code: (the function 'catchkeypress' is below)
clear;
clc;
close all;
xkey=5;
save('testp','xkey'); %saves 'xkey'
for i=1:100
load('testp','xkey'); %force script to update the variable 'xkey'
x=linspace(0,10,1000);
y=(x-xkey).^2;
plot(x,y);
axis([0,20, 0,20]);
catchKeyPress() %my function
pause(0.01)
end
and the required function:
function catchKeyPress
hkey=figure(1);
set(hkey,'KeyPressFcn',@KeyPressCb) ;
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'
save('testp','xkey');
elseif strcmpi(evnt.Key,'rightarrow') %right-arrow is pressed
xkey=xkey+0.01; %increase 'xkey'
save('testp','xkey');
end
end
end
---
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:
---
Xoffset=0;
for i=1:n %OR while condition
Xoffset=myfunction(Xoffset,RateOfChange);
y=(x-Xoffset).^2
end
---
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
Cheers,
Luc

Antworten (3)

Nirav Sharda
Nirav Sharda am 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;
x=linspace(0,10,1000);
y=(x-offset).^2;
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
guidata(f,myhandles)
plot(x,y);
% Set the KeyPressFcn Callback
set(f,'KeyPressFcn',{@myfun,1});
function myfun(src,event,rate)
% Get the structure using guidata in the callback
myhandles = guidata(src);
% If right arrow is pressed
if strcmp(event.Key,'rightarrow')
%Modify offset in the strucuture with the rate you want
myhandles.offset = myhandles.offset + rate;
% Save the change to the structure
guidata(src,myhandles)
% Get the line object which is the grand-child of the figure
% window
lineObject = src.Children.Children;
% Modify the YData of the line object.
x = lineObject.XData;
lineObject.YData = (x-myhandles.offset).^2;
end
end
I have also used the 'KeyPressFcn' callback on the figure window. I hope this helps.

Arnav Mendiratta
Arnav Mendiratta am 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);
figure(hFig);
hAxs = plot(dt,y);
function changeFreqOnKeyPress(src,event)
getKey = src.CurrentCharacter;
newFreqMultiplier = str2double(getKey);
if ~isempty(newFreqMultiplier)
newFreq = newFreqMultiplier*10
src.Children.Children.YData = sin(2*pi*newFreq*src.Children.Children.XData);
end
end

Steven Lord
Steven Lord am 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.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by