【问题标题】:Passing actual values to callback function in Matlab在 Matlab 中将实际值传递给回调函数
【发布时间】:2011-12-16 07:51:25
【问题描述】:

让我们假设以下简单示例:

f = figure;
plot(-10:10, (-10:10).^3, '*-r');
x = 1;
y = 1;
set(f, 'ResizeFcn', {@resizeCallback2, x, y});

while 1
    [x, y, button] = ginput(1);
    if(button ~= 1)
        break;
    end

    set(f, 'ResizeFcn', {@resizeCallback2, x, y});
end

%%--------------------------
function resizeCallback2(hFig, ~, foo, bar)    
    foo
    bar
end

有没有更简单的方法总是将 x 和 y 的 ACTUAL* 值传递给回调函数,而不必总是在循环中更新它? 谢谢!

【问题讨论】:

标签: matlab parameters callback


【解决方案1】:

看起来您正在尝试存储鼠标单击位置的值,然后将这些值用作调整大小函数的一部分(稍后将调用该函数)。我会做出一些改变。

首先,使用另一个回调来捕获鼠标点击,而不是 while 循环。例如,您可以使用图形ButtonDownFcn 回调来触发旨在将鼠标位置捕获到某个位置的函数。

其次,有更好的方法来存储鼠标位置,正确的方法取决于你的技能水平和程序的需要。其中一些存储数据的方法是:

  1. 在另一个回调的参数中,就像你现在正在做的那样。这很痛苦,但它可能有效。因此,如果它足以满足您的需求,您可以保留它。

  2. 大多数 Matlab 对象中的“用户数据”字段。有几个人提出了这个问题,它会很好用。我不喜欢依赖这个,因为我总是害怕其他一些工具也想使用 userdata 字段,而这些工具会覆盖数据。

  3. global 变量值。我也不喜欢使用全局变量,出于同样的原因,我不喜欢使用 userdata 字段。但是globals 有时是最好的解决方案。如果您一次只有一个人物,这可能是解决问题的最简单、最省力的方法。 (多个数字会促使您选择userdata 解决方案,这是最简单的解决方案。)

  4. 提供一个 handle 类来存储一些数据(即 x 和 y),并将该类的副本提供给两个回调(ButtonDownFcnResizeFcn)中的每一个。这允许这两个函数传递数据,而不会污染其他任何人的命名空间。对于此类问题,这是我最喜欢的解决方案,因此我将在下面对其进行更详细的描述。


要执行上面的选项 (4),需要一个类来存储如下所示的数据:

    classdef ApplicationData < handle
        properties (SetAccess = public, GetAccess = public)
            x = [];
            y = [];
        end
    end

请注意,由于ApplicationData 扩展了handle,Matlab 将其视为传递引用对象,这对我们很有用。

然后你可以创建这个类的一个实例,并把它交给每个回调函数。

    dataPassing = ApplicationData;
    set(f, 'ButtonDownFcn', @(x,y) mouseClickCapture(x,y,dataPassing));
    set(f, 'ResizeFcn',     @(x,y) resizeCallback2(x,y, dataPassing));

mouseClickCapture 看起来像这样:

    function mouseClickCapture(hAxis, ignored, dataPassingClass)
    mousePositionData = get(hAxis,'CurrentPoint');
    dataPassingClass.x = mousePositionData(1,1);
    dataPassingClass.y = mousePositionData(1,2);

你的resizeCallback2 看起来像这样:

    function resizeCallback2(h, ignored, dataPassingClass)
    %Do something here using 
    %dataPassingClass.x
    %and
    %dataPassingClass.y

【讨论】:

  • 谢谢,我真的很喜欢你的方法。我特别喜欢它,因为我实际上正在尝试做的事情是一个与“OOP”相关的问题:我的意思是我有大约 10 个变量,我需要从一个函数到另一个函数来痛苦,这些都与一个函数有关'object',因此创建某种对象并使用它的属性是一个可爱的想法:) 谢谢!此外,我喜欢你不使用 ginput 的方法:当我想在某个动作发生时以某种方式从另一个函数中止 ginput() 时,我已经遇到了问题,因为没有实际点击,所以我不能!
  • 可能只有一个问题,我在 matlab 新闻阅读器中发现:句柄类可能很慢:mathworks.com/matlabcentral/newsreader/view_thread/…
  • 我很想知道您是否在应用程序中发现同样缓慢的性能。我有两个理由怀疑你不会。首先,那篇文章是使用 2009a 编写的,Mathworks 通常会在 1-2 个版本之后修复类似的性能问题。其次,在那篇文章中最奇怪的是句柄类中的类似操作非常不同,而不是句柄类总是很慢。知道这一点(看起来很奇怪)您可能可以解决任何速度问题。也就是说,我从来没有使用过性能是一个大问题的句柄类,所以我只是不知道。
  • 到目前为止我还没有,但我还没有真正将“繁重”计算放入句柄类,因为还没有必要:) 但是,我不得不再次感谢,我使用这个解决方案几个星期了,我真的很喜欢它 :) 非常优雅和流畅!
【解决方案2】:

我不确定您实际上要做什么-也许您的简单示例掩盖了您的真实意图-但与其反复设置ResizeFcn的新版本,您可以在@987654322中存储一些东西吗@ 图形的属性,并让您的 ResizeFcn 在执行时读取它?

【讨论】:

  • 我同意,标准模式是使用UserData。比改ResizeFcn清晰多了。
  • 谢谢,不知道有这样一个字段来存储东西......但我仍然必须在每次迭代中更新 UserData 的值。
  • 没错——为什么会出现这样的问题?你最终真正想要做什么,而不是简单的例子?
猜你喜欢
  • 1970-01-01
  • 2019-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多