我正在尝试使用左右箭头键更改球体的半径,并在MATLAB图中绘制。例如,通过按向右箭头,半径值增加1,然后使用更新的半径绘制新球体。同样,按左箭头键可将半径减小一,然后绘制一个较小的球体。但是,我希望此更改仅限于1和rmax
之间。
我在阅读this post之后得到了一些关于我如何处理的想法,但它仍然不是我想要的。因此,我使用两个全局变量来完成此任务,以便通过引用KeyPressFcn
以某种方式传递信息,因此当按下某个键时KeyPressFcn
知道这些限制是什么。在下面的示例中,代码确实将半径增大或减小一个,但是在左箭头和右箭头被击中后,它不会限制半径在指定范围内的变化。
有没有更好的方法来接近这个?如何将radius的值及其限制传递给KeyPressFcn
?我希望KeyPressFcn
知道在按下左箭头和右箭头时它可以改变半径。
function animateme()
fig_h = figure;
set(fig_h,'KeyPressFcn', @key_pressed_fcn);
global r rmax
p0 = [0 0 0];
[x,y,z] = sphere;
rmax = 10;
r = 1;
while 1==1
h = surf(x*r+p0(1), y*r+p0(2), z*r+p0(3));
set(h, 'FaceAlpha', 0.5, 'FaceColor', rand([1 3]))
axis equal;
pause
end
function key_pressed_fcn(fig_obj, eventDat)
global r rmax
if strcmpi(eventDat.Key, 'rightarrow')
r = r + 1;
if r < 1
r = 1;
end
elseif strcmpi(eventDat.Key, 'leftarrow')
r = r - 1;
if r > rmax
r = rmax;
end
end
disp(r)
答案 0 :(得分:4)
首先,不要使用全局变量,因为(几乎)总是有更好的方法来完成同样的事情。
这是一个使用嵌套函数的示例,它们可以自动访问父函数工作区中的变量。
function animateme()
fig = figure();
hax = axes('Parent', fig);
set(fig, 'KeyPressFcn', @keypress)
p0 = [0,0,0];
[x,y,z] = sphere();
% Specify limits here which are accessible to nested functions
rmax = 10;
r = 1;
h = surf(x,y,z, 'Parent', hax);
% Subfunction for re-plotting the data
% This prevents you from needing a while loop
function redraw()
set(h, 'XData', x * r + p0(1), ...
'YData', y * r + p0(2), ...)
'ZData', z * r + p0(3));
set(h, 'FaceAlpha', 0.5, ...
'FaceColor', rand([1 3]))
axis(hax, 'equal')
drawnow
end
% Go ahead and do the first redraw
redraw();
% Callback to process keypress events
function keypress(~, evnt)
switch lower(evnt.Key)
case 'rightarrow'
r = min(r + 1, rmax);
case 'leftarrow'
r = max(1, r - 1);
otherwise
return
end
% Always do a redraw
redraw();
end
end
另一种选择是使用r
字段将UserData
的当前值存储在图形对象本身中。所以你可以把它放在surf
情节本身。这实际上是我首选的方法,因为您的回调函数可以在任何地方生活,并且仍然可以访问所需的数据。
function animateme()
fig = figure();
% Data to store for plotting
data.p = [0,0,0];
data.r = 1;
data.rmax = 10;
% Create a blank surface for starters
h = surf(nan(2), nan(2), nan(2));
set(h, 'UserData', data);
% Update the display of the surface
redraw(h);
% Set the callback and pass the surf handle
set(fig, 'KeyPressFcn', @(fig, evnt)keypress(h, evnt))
end
function redraw(h)
% Get the stored data from the graphics object
userdata = get(h, 'Userdata');
[x,y,z] = sphere();
set(h, 'XData', x * userdata.r + userdata.p(1), ...
'YData', y * userdata.r + userdata.p(2), ...
'ZData', z * userdata.r + userdata.p(3));
set(h, 'FaceAlpha', 0.5, ...
'FaceColor', rand([1 3]))
axis equal
drawnow;
end
function keypress(h, evnt)
% Get the stored data
userdata = get(h, 'Userdata');
switch lower(evnt.Key)
case 'rightarrow'
userdata.r = min(userdata.r + 1, userdata.rmax);
case 'leftarrow'
userdata.r = max(1, userdata.r - 1);
otherwise
return;
end
% Update the stored value
set(h, 'UserData', userdata);
redraw(h);
end