在 MATLAB for Mac 中启用选项键快捷键

2024-01-07

自 R2009b 以来,MATLAB 通过其出色的可自定义键盘快捷键键盘快捷键首选项 http://blogs.mathworks.com/desktop/2009/09/28/configurable-keyboard-shortcuts-have-arrived/。这对于在 Mac 上使用命令和控制自定义快捷方式非常有效。

不幸的是,这些键绑定似乎无法覆盖 MATLAB 的内置字符映射表。例如,如果我将 option-f 定义为cursor-next-word(a la emacs),它接受绑定。按组合键确实可以将光标正确移动到下一个单词,但它还会打印ƒ特点!我相信这是来自字符映射(也许与输入映射相反?)。两者都不编辑器宏 http://www.mathworks.com/matlabcentral/fileexchange/24615-editormacro-assign-a-macro-to-a-keyboard-key-stroke-in-the-matlab-editor-and-command-window nor 按键绑定 http://www.mathworks.com/matlabcentral/fileexchange/25089能够覆盖此行为。

我偶然发现这个答案来自一个切线相关的问题 https://stackoverflow.com/questions/1759413/how-do-i-make-a-character-in-matlab/1786487#1786487这给了我希望。简而言之,他定义了一个Java类,可以处理键盘事件并用其他击键输入替换它们。然而,该解决方案仅在 Windows 上按规定工作。要在 Mac 上运行,需要进行以下修改:

我需要更改键码以重新映射以在字符串中包含“pressed”,如下所示:

map = {
    '$' '^'
    '#' char(181)  % might be useful for text formatting
};

to:

map = {
    'alt pressed F' '^'
    'alt pressed B' char(181)  % might be useful for text formatting
};

不幸的是,运行代码后,按 option-f 会产生cursor-next-wordƒ性格,和以前一样。但是,如果我禁用cursor-next-word从首选项绑定,然后我得到both ƒ and ^!事实上,即使我使用像这样的简单动作pressed F,KeyReplacementAction 不会替换操作,而是augments它。这种行为似乎是 OS X 上的 MATLAB 所独有的。

似乎我根本没有覆盖正确的键盘映射。我尝试深入研究 Java 运行时,但我对事件分派模型不够熟悉,不知道下一步该去哪里。也许是 Java 操作系统级键盘映射中的某些东西?


Edit: 从那以后我又做了一些挖掘。看来 Mac 版本的 MATLAB 没有正确尊重 keyEvent 的“consumed”属性。我可以将 KeyReplacementAction 附加到inputMap or the keymap,并且在这两种情况下,我都会增强键绑定而不是替换它。我使用反射来“取消保护”consume()AWTEvents 的方法,但效果和以前一样。

跟踪堆栈跟踪,看起来好像 keyEvent 正在下降到一个实例javax.swing.KeyboardManager。看起来我应该能够在 KeyboardManager 中解除按键绑定,但我无法弄清楚如何从我拥有的 MATLAB 句柄访问该实例。也许更熟悉 Swing 事件模型和 Java 调试器的人可以走得更远。


Edit 2: flolo https://stackoverflow.com/users/36472/flolo的回答促使我研究 X11 的键盘映射。几点注意事项:

  • Matlab似乎不尊重~/.Xmodmap或任何当前加载的 modmap。
  • Matlab 利用$XKEYSYMDB环境变量(如果启动时存在)。否则,它会从$MATLAB/X11/app-defaults/XKeysymDB.
  • 整体$MATLAB/X11/app-defaults/目录看起来很有趣;也许那里的一些黑客可以让这个工作成功?
  • Where areMac 上的 X11 键映射? MATLAB 如何切换到国际键盘布局?

Edit 3:嗯,我认为 X11 是一个转移注意力的话题。lsof -c MATLAB显示正在访问/System/Library/Keyboard Layouts/AppleKeyboardLayouts.bundle。现在正在努力……


Edit 4:MATLAB 确实使用系统键盘布局。我创建了一个没有任何绑定的R.M. https://stackoverflow.com/users/616736/r-m建议。这似乎有效 — MATLAB 确实表现正常。不幸的是,它也破坏了我在所有其他程序中的自定义 Cocoa 键绑定。接近,但没有雪茄。 (事实上​​,R.M. 已经很接近了,因为短暂的想法它已经起作用了,所以 R.M. 赢得了 +500 赏金……直到我试图撰写我的祝贺评论并发现我无法像往常一样导航文本字段。)


我终于有机会在假期里进一步追求这个目标。我找到了一个解决方案。请注意,这是在运行时动态更改 Matlab GUI 使用的 Java 类;它完全没有支撑,并且可能非常脆弱。它适用于我的 OS X Lion 版本的 Matlab (r2011a)。

以下是我了解到的 Swing/Matlab 如何处理按键事件的知识:

  1. 按下按键。
  2. The active text component's inputMap is searched to see if there's a binding for that keystroke.
    • 如果有一个操作绑定到该击键,则调度该操作的actionPerformed method
    • 如果存在与该击键关联的字符串,则从文本组件的actionMap,然后调度该操作的actionPerformed method
  3. 无论作为最后一步,调度在文本组件中找到的操作Keymap.getDefaultAction()。问题就出在这里。

此解决方案使用包装器覆盖键盘映射的默认操作,该包装器仅检查是否按下了任何修饰键。如果是的话,该操作将被默默地忽略。


第 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 内部)中覆盖 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')
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 MATLAB for Mac 中启用选项键快捷键 的相关文章

随机推荐

  • 一次读取每个字符 - C

    对于下面的question https users cs cf ac uk Dave Marshall C node7 html SECTION00730000000000000000 练习 12336 从程序的标准输入中一次读取一个字符的
  • 将整数转换为随机但确定性可重复的选择

    如何将无符号整数 表示用户 ID 转换为看起来随机但实际上是确定性可重复的选择 必须以相等的概率选择该选项 无论输入整数的分布如何 例如 如果我有 3 个选择 即 0 1 2 例如 用户ID 123可以总是被随机分配选择2 而用户ID 23
  • git 日志格式中可选的缩进换行符

    我一直在摆弄git一些的别名log命令 我已经拥有了大部分我想要的东西 信用在这里 https stackoverflow com a 9074343 241211 但我在一件事情上遇到了麻烦 当我打电话时 git log graph fo
  • Android JNI - 调用 AttachCurrentThread 而不使用 DetachCurrentThread

    我一直在阅读有关 JNI 的内容 似乎无法弄清楚如果线程启动 gt 调用 AttachCurrentThread gt 进行一些 JNI 调用 gt 线程退出会发生什么 理想情况下 我们应该在线程退出之前调用 DetachCurrentTh
  • 通过C#发送截图

    我通过该代码捕获屏幕截图来保存 Graphics Grf Bitmap Ekran new Bitmap Screen PrimaryScreen Bounds Width Screen PrimaryScreen Bounds Heigh
  • Java中的双重比较技巧

    C 允许您将两个整数比较合并为一个以进行范围检查 例如 unsigned X lt unsigned Upper 当 0 lt X lt Upper Java 语言没有无符号类型 您是否找到了一种方法来获得相同的效果 使用单个比较并且没有太
  • 如何运行 OCaml + Core 脚本?

    我正在尝试 Real World OCaml 这本书 它讨论了安装 OPAM 然后是 OCaml 和 Jane Street Core 我按照书中的说明正确加载了 utop 以便它自动加载 Core 没有 Core 我可以简单地运行通用 O
  • 坚持将 GCP 项目转移到组织

    我正在尝试将 GCP 项目 在私人帐户上 移至我管理的 GCP 组织 我知道我必须拥有正确的 IAM 权利 我相信我也这样做 我是项目中的所有者 文件夹管理员 组织管理员 项目删除者和项目移动者 我也是要搬迁项目的项目所有者和项目搬家者 但
  • “已杀:9”错误是什么意思?

    我正在编写一个程序来查找给定字符串的所有子集 然而 它会导致一个名为的错误Killed 9 class Strings object def init self string self list1 self string string de
  • Python 2.7 中枚举不可迭代

    from enum import Enum class Shake Enum order vanilla chocolate cookies mint only needed in 2 x vanilla 7 chocolate 4 coo
  • Javascript(动态)插入数组,然后将所有元素移到+1下面

    没有真正找到 Javascript 的解决方案 我需要的 我想将一个元素插入数组 但并不真正覆盖该元素 而是 动态 插入 因此插入元素 然后将其下面的所有元素移动 1 索引 例如 I have an array 14S 16S 19S I
  • Vim 配色方案更改

    我很难改变我的配色方案 我已经打开 vimrc 和 usr share vim vimrc 并添加 colorscheme desert 没事了 我注意到配色方案在这里 usr share vim vim72 colors desert v
  • Twilio 错误 - 12300 - 仅有时内容类型无效

    我有一个与数字绑定的 C NET WebApi 端点 当该号码收到短信时 它会通过 webhook 转发到我的 API 有时 并非总是 我的调试器中会出现以下错误 错误 12300 内容类型无效 Twilio 无法处理所提供 URL 的内容
  • Vue 3 中的自定义指令

    我正在尝试创建一个自定义指令来在单击元素时执行函数 我无法让它工作 我查看了自定义指令的文档 甚至直接从那里复制示例也不起作用 我正在使用单个文件模板和本地指令 这是模板
  • 不满足特征绑定“T: std::fmt::Display”

    我正在编写一个基本的二叉树结构 我想显示一个节点 Rust 似乎无法显示泛型类型 我收到此错误 error E0277 the trait bound T std fmt Display is not satisfied gt src ma
  • 在 Java 中:为什么某些 Stream 方法采用 int 而不是 byte 甚至 char?

    为什么有些方法会这样写bytes chars到流需要int代替byte char 有人告诉我如果出现以下情况int 而不是char 因为char在java中只有2个字节长度 这对于大多数已经使用的字符符号来说是可以的 但是对于某些字符符号
  • 如何根据值对 pandas 系列进行子集化?

    我有一个 pandas 系列对象 我想根据一个值对其进行子集化 例如 s pd Series 1 2 3 4 5 6 7 8 9 10 我如何对其进行子集化 以便获得仅包含大于或小于 x 值的元素的系列对象 我相信你指的是布尔索引 http
  • Outlook 365 加载项仅出现在 Outlook 2013 客户端中

    我在 Outlook 2016 中显示我的加载项时遇到问题 我将其开发为 Office365 加载项 它在 Outlook 2013 中的工作方式就像一个超级按钮 但当时我想在 Outlook 2016 中测试它 但它没有显示在 Offic
  • 错误:发送后无法设置标头。 - NodeJS 和 Express

    我有一个 NodeJS Rest API 其中有一个用户集合 此外我还进行用户短信验证 这是 POST 的控制器 id verification exports verification req res gt const id req pa
  • 在 MATLAB for Mac 中启用选项键快捷键

    自 R2009b 以来 MATLAB 通过其出色的可自定义键盘快捷键键盘快捷键首选项 http blogs mathworks com desktop 2009 09 28 configurable keyboard shortcuts h