我终于有机会在假期中进一步追求这一点。我找到了一个解决方案。请注意,这是动态更改Matlab GUI在运行时使用的Java类;它完全不受支持,并且可能非常脆弱。它适用于我在OS X Lion上的Matlab(r2011a)版本。
以下是我了解的 Swing/Matlab 如何处理按键事件的信息:
- 按下击键。
- 搜索活动文本组件以查看该击键是否存在绑定。
inputMap
- 如果存在绑定到该击键的操作,请调度该操作的方法
actionPerformed
- 如果存在与该击键关联的字符串,请从文本组件的 中找到该操作,然后调度该操作的方法
actionMap
actionPerformed
-
无论如何,作为最后一步,分派在文本组件的 .这就是问题所在。
Keymap.getDefaultAction()
此解决方案使用包装器覆盖 Keymap 的默认操作,该包装器仅检查是否按下了任何修饰键。如果是这样,则该操作将被默默忽略。
步骤 1:在 Java 中创建自定义文本操作以忽略修饰键
import javax.swing.text.TextAction;
import javax.swing.Action;
import java.awt.event.ActionEvent;
public class IgnoreModifiedKeystrokesAction extends TextAction
{
private static final int ignoredModifiersMask =
ActionEvent.CTRL_MASK | ActionEvent.ALT_MASK;
private Action original;
public IgnoreModifiedKeystrokesAction(Action act)
{
super((String)act.getValue("Name"));
original = act;
}
public void actionPerformed(ActionEvent e)
{
if ((e.getModifiers() & ignoredModifiersMask) == 0) {
/* Only dispatch the original action if no modifiers were used */
original.actionPerformed(e);
}
}
public Action getOriginalAction()
{
return original;
}
}
编译为 :.jar
javac IgnoreModifiedKeystrokesAction.java && jar cvf IgnoreModifiedKeystrokesAction.jar IgnoreModifiedKeystrokesAction.class
步骤 2:在命令窗口和编辑器中覆盖 MATLAB 的默认 Keymap 处理程序(从 MATLAB 内部)
这里最困难的部分是将java句柄获取到命令窗口和编辑器。它取决于各个编辑器窗格的布局和类名。这可能会在 Matlab 的不同版本之间发生变化。
javaaddpath('/path/to/IgnoreModifiedKeystrokesAction.jar')
cmdwin = getCommandWindow();
editor = getEditor();
for t = [cmdwin,editor]
defaultAction = t.getKeymap().getDefaultAction();
if ~strcmp(defaultAction.class(),'IgnoreModifiedKeystrokesAction')
newAction = IgnoreModifiedKeystrokesAction(defaultAction);
t.getKeymap().setDefaultAction(newAction);
end
end
%% Subfunctions to retrieve handles to the java text pane elements
function cw = getCommandWindow()
try
cw = handle(com.mathworks.mde.desk.MLDesktop.getInstance.getClient('Command Window').getComponent(0).getComponent(0).getComponent(0),'CallbackProperties');
assert(strcmp(cw.class(),'javahandle_withcallbacks.com.mathworks.mde.cmdwin.XCmdWndView'));
catch %#ok<CTCH>
cw_client = com.mathworks.mde.desk.MLDesktop.getInstance.getClient('Command Window');
cw = searchChildComponentsForClass(cw_client,'com.mathworks.mde.cmdwin.XCmdWndView');
end
if isempty(cw)
error('Unable to find the Command Window');
end
end
function ed = getEditor()
try
ed = handle(com.mathworks.mde.desk.MLDesktop.getInstance.getGroupContainer('Editor').getComponent(1).getComponent(0).getComponent(0).getComponent(0).getComponent(1).getComponent(0).getComponent(0).getComponent(0).getComponent(0).getComponent(1).getComponent(0).getComponent(0),'CallbackProperties');
assert(strcmp(ed.class(),'javahandle_withcallbacks.com.mathworks.mde.editor.EditorSyntaxTextPane'));
catch %#ok<CTCH>
ed_group = com.mathworks.mde.desk.MLDesktop.getInstance.getGroupContainer('Editor');
ed = searchChildComponentsForClass(ed_group,'com.mathworks.mde.editor.EditorSyntaxTextPane');
% TODO: When in split pane mode, there are two editor panes. Do I need
% to change actionMaps/inputMaps/Keymaps on both panes?
end
if isempty(ed)
error('Unable to find the Editor Window');
end
end
function obj = searchChildComponentsForClass(parent,classname)
% Search Java parent object for a child component with the specified classname
obj = [];
if ~ismethod(parent,'getComponentCount') || ~ismethod(parent,'getComponent')
return
end
for i=0:parent.getComponentCount()-1
child = parent.getComponent(i);
if strcmp(child.class(),classname)
obj = child;
else
obj = searchChildComponentsForClass(child,classname);
end
if ~isempty(obj)
obj = handle(obj,'CallbackProperties');
break
end
end
end
现在,可以在使用选项键的标准首选项窗口中定义键绑定!
步骤 3(可选):删除自定义操作
cmdwin = getCommandWindow();
editor = getEditor();
for t = [cmdwin,editor]
defaultAction = t.getKeymap().getDefaultAction();
if strcmp(defaultAction.class(),'IgnoreModifiedKeystrokesAction')
oldAction = defaultAction.getOriginalAction();
t.getKeymap().setDefaultAction(oldAction);
end
end
javarmpath('/path/to/IgnoreModifiedKeystrokesAction.jar')