【问题标题】:Getting Matlab handles events or properties获取 Matlab 处理事件或属性
【发布时间】:2013-08-25 16:52:12
【问题描述】:

问题

我如何获得双精度类型句柄的事件和属性列表,例如 figureaxes

问题

Matlab 文档要求您使用WindowButtonDownFcnWindowButtonMotionFcn 等来收听界面上发生的任何事情。问题是这个属性非常有限,因为the following fact:

将变量保持在范围内

当 MATLAB 计算函数句柄时,相同的变量在 范围与创建函数句柄时一样。(相反,回调 指定为字符串在基础工作区中进行评估。)这 简化了管理全局数据的过程,例如对象 句柄,在 GUI 中。

是的,这是完美的,如果您不必从 ButtonDownFcn 重新定义、添加或删除回调,因为如果这样做,您将失去其他函数句柄变量范围,因为你在一个新的范围内声明它们,可能肯定不会包含你需要的变量。

因此,一种方法是监听事件本身,而不是在事件激活时调用的属性,这样做,您不必费心重新声明 ButtonDownFcn 以及如何将变量保持在范围内,因为其他解决方案实施起来非常缓慢!。如果我可以像使用handle.listeneraddlistener matlab 监听工具那样直接监听事件,我就不必为此烦恼了。

一种已知的好方法

似乎最好的解决方案之一是 this FEX,它赋予了弱 matlab WindowButtonDownFcnWindowButtonDownFcn 以及 matlab 具有的任何属性“监听器”功能,因此您可以拥有任意数量的函数来监听变化您的图形界面,而不必关心您的其他函数句柄是否会丢失它们的范围变量。

有了这个,我不需要获取 matlab 事件,因为它为我包装了所有内容。但是,matlab 引导您的用户使用损坏的功能而不是记录更好的方法并引导人们将所有内容包装起来,以便他们可以按应有的方式使用东西,这仍然让我感到有趣。


可能有用的信息。

我知道meta.class 会给我一个类所具有的所有属性、事件等。对于我有一个继承自handle 的类:

>> EventMeta = ?Event
EventMeta = 

  class with properties:

                     Name: 'Event'
              Description: ''
      DetailedDescription: ''
                   Hidden: 0
                   Sealed: 0
                 Abstract: 0
          ConstructOnLoad: 0
         HandleCompatible: 1
          InferiorClasses: {0x1 cell}
        ContainingPackage: []
             PropertyList: [64x1 meta.property]
               MethodList: [29x1 meta.method]
                EventList: [2x1 meta.event]
    EnumerationMemberList: [0x1 meta.EnumeratedValue]
           SuperclassList: [1x1 meta.class]

使用该元数据,我可以从 Event 类中获取 EventList,它们是:

>> EventMeta.EventList.Name

ans =

attemptToClick


ans =

ObjectBeingDestroyed

好吧,在这种情况下,这并不是一件好事,因为我已经实现了它并且我知道它所具有的事件,因为我有源代码。问题是,如果我可以获得 figure 的元类(如果可能的话),我可以访问其实现的 Events(如果它们在 matlab 上可用)。

【问题讨论】:

    标签: matlab user-interface reflection event-handling handle


    【解决方案1】:

    在底层,Handle Graphics (HG) 是使用未记录的 UDD 机制实现的,而不是向用户公开的通常的 classdef 样式 OOP。

    这就是为什么您不能直接使用meta.class 系统来获取有关此类句柄的元信息。

    正如您在 Yair Altman's blog 上已经发现的那样,有一些未记录的方式来监听事件:

    fig = hg.figure(); plot(rand(100,1))
    lh = handle.listener(fig, 'WindowButtonDownEvent',@(~,~)disp('clicked'));
    

    如果您已经有一个现有的 HG 对象句柄(用数字句柄表示),请使用 handle 将其转换为 UDD 句柄:

    f = figure();
    fig = handle(f);
    

    是的,我知道,handle 一词在 MATLAB 中非常重载,可能指代很多东西

    【讨论】:

    • 事实上,我打算发布 HG2 将使用一种meta.class 兼容的方法。我认为 matlab 并没有试图改进句柄图形机制,因为他们正在用它来代替新的。现在一切都说得通了,为什么在使用手柄图形时一切都如此混乱。我希望他们能正确记录 HG2,至少通过meta.class 访问它会变得相当容易。
    • @Werner: 是的HG2 应该是下一件大事,但我怀疑升级是否会很快发生。当前的 HG 系统已经存在了很长时间,并附有很多遗产......
    【解决方案2】:

    当我改进我的问题时,我设法找到了答案(不幸的是,我之前似乎没有在搜索中找到它们,更糟糕的是,我之前打开的一些链接......)

    这里的undocummented matlab blog 展示了如何从 matlab 句柄对象中获取句柄。似乎已经在 2011 年就这个问题 here in stackoverflow 提出了一个关于此问题的问题,并由 @gnovice 正确回答。答案是:

    >> get(get(classhandle(handle(gcf)),'Events'),'Name')
    ans = 
        'SerializeEvent'
        'FigureUpdateEvent'
        'ResizeEvent'
        'WindowKeyReleaseEvent'
        'WindowKeyPressEvent'
        'WindowButtonUpEvent'
        'WindowButtonDownEvent'
        'WindowButtonMotionEvent'
        'WindowPostChangeEvent'
        'WindowPreChangeEvent'
    

    我仍然想提请您注意 FEX,这是另一个很好的解决方案,它可以让您更好地使用 matlab 提供的图形组件。

    使用示例:

    >> k=handle.listener(gcf,'WindowButtonMotionEvent','disp(''MOVEMENT DETECTED!!'')');   
    >> MOVEMENT DETECTED!! % When you move the mouse on the figure
    >> MOVEMENT DETECTED!!
    >> MOVEMENT DETECTED!!
    >> MOVEMENT DETECTED!!
    >> MOVEMENT DETECTED!!
    >> MOVEMENT DETECTED!!
    >> delete(k)
    

    【讨论】:

    • 刚刚发现了一些关于这个的好东西!!有空的时候可以发一下。现在,为什么一切都变得如此混乱是有道理的……
    【解决方案3】:

    尝试使用 get:

    fig = gcf();
    get(fig)
    

    【讨论】:

    • 是的,这给了我属性,我知道,但这不会给我事件 x(
    • 通过事件,您是指在 sum 操作时执行的函数吗?这些被列为属性,通常带有后缀“Fcn”。
    • 别忘了@。 'Fcn' 是属性,而不是使用notify 引发的触发事件,并且可能是handle.listener 对象或使用addlistener 函数(将创建handle.listener 并将其添加到matlab 侦听器堆栈。当您有几个地方修改 Fcn 属性时,Fcn 属性非常有限......
    【解决方案4】:

    我不知道该怎么做。我可以提供一些示例代码来演示我认为被问到的内容。这是一个相对较新(因此未使用)的 Matlab 功能:

    hh = handle(gca);
    lsnr = addlistener(hh,'XLim','PreGet',@(~,~)disp('<<<Getting XLIM values>>>'))
    

    查看监听器的运行情况

    >> get(hh,'XLim')
    <<<Getting XLIM values>>>
    ans =
         0     1
    

    我认为问题是如果没有存储值,如何从gca 获取lsnr

    我找不到路。

    【讨论】:

    • 顺便说一句,如果这是正确的解释,您应该将代码添加到原始问题中。
    • 谢谢,但我认为我的问题不是很清楚。我会尽快编辑它并提供更多信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-30
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多