Labfans是一个针对大学生、工程师和科研工作者的技术社区。 | 论坛首页 | 联系我们(Contact Us) |
![]() |
![]() |
#1 |
高级会员
注册日期: 2019-11-21
帖子: 3,006
声望力: 66 ![]() |
![]()
从R2009b开始,MATLAB通过其Keyboard Shortcuts Preferences拥有了可定制的键盘快捷键 。这对于在Mac上使用命令和控制来自定义快捷方式非常有效。
不幸的是,这些键绑定似乎无法覆盖MATLAB的内置字符映射。例如,如果我将option-f定义为cursor-next-word (la emacs),则它接受绑定。击中组合键,光标不会正确地移动到下一个词,但它另外打印茠字符!我相信这是从字符映射表(也许与输入映射表相反?)中获得的。 EditorMacro和KeyBindings均不能覆盖此行为。 我从一个与切向相关的问题中偶然发现了这个答案,这给了我希望。简而言之,他定义了一个Java类,该类可以处理键盘事件并将其替换为其他按键输入。但是,该解决方案只能在Windows上按规定使用。在Mac上运行需要进行以下修改: 我需要更改键码以重新映射字符串中的“按下”键,如下所示: map = { '$' '^' '#' char(181) % might be useful for text formatting }; 至: map = { 'alt pressed F' '^' 'alt pressed B' char(181) % might be useful for text formatting }; 不幸的是,在运行代码,按下Option-F键的产量后cursor-next-word和茠性格,就像以前一样。但是,如果我从首选项中禁用了cursor-next-word绑定,那么我会同时获得茠和^ !确实,即使我使用了一个简单的动作(例如pressed F ,KeyReplacementAction也不代替该动作,而是对其进行了增强 。似乎此行为是OS X上的MATLAB特有的。 似乎我只是没有覆盖正确的键盘映射。我已经尝试了Java运行时的挖掘,但是我对事件分发模型并不足够了解,因此不知道下一步该怎么看。也许在Java的操作系统级键盘映射中? 编辑 :从那以后我做了更多的挖掘。似乎Mac版本的MATLAB并未正确遵守keyEvent的'consumed'属性。我可以将KeyReplacementAction附加到inputMap或keymap ,在两种情况下,我都增加了键绑定而不是替换键绑定。我使用反射来“取消保护” AWTEvents的consume()方法,但效果与以前相同。 在堆栈跟踪之后,似乎keyEvent陷入了javax.swing.KeyboardManager的实例。看起来我应该能够在KeyboardManager中解除键击的绑定,但是我无法弄清楚如何从已有的MATLAB句柄访问实例。也许更熟悉Swing的事件模型和Java调试器的人可能会走得更远。 编辑2 : flolo的答案促使我研究X11的键盘映射。几点注意事项:
回答: 我终于有机会在假期里进一步追求这一点。我发现了解决方案的麻烦。注意,这是在运行时动态更改Matlab GUI使用的Java类。它是完全不受支持的,并且可能非常脆弱。它可以在我的OS X Lion版本的Matlab(r2011a)上运行。 这是我对Swing / Matlab如何处理按键事件的了解:
步骤1:在Java中创建自定义TextAction来忽略修饰键 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 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 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') 更多&回答... |
![]() |
![]() |