我有一个我设计的用户界面,我希望让某些按键在用户界面中启动一些操作。我尝试为图形的 keypressfcn 回调定义一个函数,但如果任何其他 UI 元素是活动元素,则调用该元素的 keypressfcn(为空)。如何在不为 UI 中的所有子元素分配相同的 keypressfcn 函数句柄的情况下捕获整个图形的按键?
2 回答
我发现 WindowKeyPressFcn 回调做了我想要的。这是图形的一个属性,但要注意,它完全按照它所说的去做 - 它在这是活动图形时捕获按键(不管活动元素是什么)。考虑一下你是否真的想要这个,例如当一个编辑元素有焦点时,WindowKeyPressFcn 将在它被输入时触发。
恐怕你必须定义每一个uicontrol
's KeyPressFcn
。想一想:如果您设计了 Matlab,您将如何同时保持选项开放,让用户为不同的 分配不同的按键功能uicontrols
,同时还允许他们对所有人只使用一个主功能uicontrols
?
每个新人uicontrol
都必须知道你想这样做,这等于分配它的KeyPressFcn
.
最简单的方法是编写一些通用函数,例如
function KeyPressFcnFwd(obj,event)
prn = get(obj, 'parent')
fcn = get(prn, 'KeyPressFcn');
fcn(prn,event);
end
然后像这样定义uicontrols:
button = uicontrol(...
'style', 'pushbutton', ...
...
'KeyPressFcn', @KeyPressFcnFwd);
这样做会使某个单选按钮上的按键调用其父级的 KeyPressFcn
,这是一个单选组,后者又将呼叫转发到其父级的KeyPressFcn
,这是一个 uipanel,后者又将呼叫转发到其父级的KeyPressFcn
,最后是你的身影KeyPressFcn
。
简而言之:无论你uicontrol
的嵌套有多深,调用总是会一直转发到图上。
如果将此函数定义为创建“主”图形的函数中的嵌套函数,则可以更有效地完成所有操作:
function main %# toplevel function
...
mainFig = figure(...) %# your main figure
...
%# nested function
function KeyPressFcnFwd(obj,event)
fcn = get(mainFig, 'KeyPressFcn');
fcn(mainFig,event);
end
...
%# Function to build the GUI
%# can be a subfunction, nested function or external function
populateMainWin(mainFig, @KeyPressFcnFwd);
...
end
这样你就没有调用整个树的开销KeyPressFcn
。
在可能有很多样板的情况下(这是一个很好的候选),我通常定义一些速记,比如
function handle = uibutton(parent, text, varargin)
handle = uicontrol(...
'parent', parent, ...
'style' , 'pushbutton', ...
'units' , 'normalized', ...
'string', text, ...
'KeyPressFcn', @KeyPressFcnFwd, ...
varargin{:});
end
这样我的代码仍然可读。