matlab - 通过按向左和向右箭头键为 MATLAB 图制作动画

标签 matlab callback pass-by-reference matlab-figure

我正在尝试使用左右箭头键更改球体的半径,绘制在 MATLAB 图形中。例如,按向右箭头,半径值增加 1,然后用更新后的半径绘制新球体。同样,按向左箭头键将半径减小一,然后绘制一个较小的球体。但是,我希望将此更改限制在 1 和 rmax 之间。

阅读 this post 后,我对如何处理有了一些想法但它仍然不是我想要的。因此,我使用了两个全局变量来完成此任务,以便通过引用 KeyPressFcn 以某种方式传递信息,以便在按下某个键时 KeyPressFcn 知道这些限制是什么。在下面的示例中,代码确实将半径增加和减少了一个,但它并没有限制点击左右箭头后半径在指定范围内的变化。

有没有更好的方法来解决这个问题?如何将半径值及其限制传递给 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)

最佳答案

首先,不要使用全局变量,因为(几乎)总是有更好的方法来完成同样的事情。

下面是一个使用嵌套函数的示例,它可以自动访问父函数工作区内的变量。

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

另一种选择是使用 UserData 字段将 r 的当前值存储在图形对象本身中。所以你可以把它放在 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    

关于matlab - 通过按向左和向右箭头键为 MATLAB 图制作动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35779275/

相关文章:

image - Matlab梯度和OpenCV梯度给出不同的结果

matlab - 计算多个多项式的根

javascript - jQuery 通过父函数返回 $.post 回调

c++ - 如何为模板回调参数强制执行特定签名

javascript - 在 JavaScript 中回调后交替操作的更好方法

javascript强制更新输入框上的ng-model值

c++ - 为什么我们必须将值而不是地址传递给 C++ 中的 "call by reference"函数?

python - python 中类似 matlab 的复杂数据结构(numpy/scipy)

Matlab函数adapt()似乎不起作用

php - 通过引用函数传递字符串会加快速度吗? (php)