问题
如何获取双重类型句柄(如figure
、axes
)的事件和属性列表
问题
Matlab文档告诉您要使用WindowButtonDownFcn
、WindowButtonMotionFcn
等等,以便监听接口上发生的任何事情。问题是,由于以下事实,这种属性非常有限:
将变量保持在范围内
当MATLAB评估函数句柄时,中存在相同的变量创建函数句柄时的作用域(相比之下,回调指定为在基本工作区中计算的字符串。)这个简化了管理全局数据的过程,例如对象句柄,在GUI中
是的,这是完美的,如果您不必重新定义、添加或删除ButtonDownFcn中的回调,因为如果您这样做,您将失去其他函数句柄变量作用域,因为您正在一个新作用域中声明它们,而可能肯定不会包含您所需的变量。
因此,一种方法是监听事件本身,而不是在事件处于活动状态时调用的属性。这样做,您就不必重新声明ButtonDownFcn以及如何将变量保持在范围内,因为其他解决方案实现起来非常慢。如果我可以像使用handle.listener
或addlistener
matlab监听工具那样直接监听事件,我就不必为此烦恼了。
一个已知的好方法
最好的解决方案之一似乎是这个FEX,它赋予了弱的matlab WindowButtonDownFcn
、WindowButtonDownFcn
和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
的元类(如果可能的话),如果它们在matlab中可用,我就可以访问它实现的Events
。
在后台,Handle Graphics(HG)是使用未记录的UDD机制实现的,而不是向用户公开的常见classdef
风格的OOP。
这就是为什么您不能直接使用meta.class
系统来获取此类句柄的元信息。
正如你在亚伊尔·奥特曼的博客上已经发现的那样,有一些未记录的方式可以收听事件:
fig = hg.figure(); plot(rand(100,1))
lh = handle.listener(fig, 'WindowButtonDownEvent',@(~,~)disp('clicked'));
如果您已经有一个现有的HG对象句柄(用数字句柄表示),请使用handle
将其转换为UDD句柄:
f = figure();
fig = handle(f);
是的,我知道,术语handle
在MATLAB中是相当过载的,可能指的是
当我改进我的问题时,我设法找到了答案(不幸的是,我以前在搜索中似乎没有见过它们,更糟糕的是,一些我以前打开过的链接…)
在这里,未累积的matlab博客展示了如何从matlab句柄对象中获取句柄。2011年,似乎已经有一个关于这个问题的问题在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)
尝试使用get:
fig = gcf();
get(fig)
我不知道该怎么做。我可以提供一些示例代码来演示我所认为的问题。这是一个相对较新(因此未使用)的Matlab功能:
hh = handle(gca);
lsnr = addlistener(hh,'XLim','PreGet',@(~,~)disp('<<<Getting XLIM values>>>'))
查看正在进行的侦听器
>> get(hh,'XLim')
<<<Getting XLIM values>>>
ans =
0 1
我认为问题是,如果没有存储值,如何从gca
中获取lsnr
。
我找不到路了。