You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现JTextPane缩写监听器?支持Ctrl+Enter触发替换

实现方案与示例

核心思路

不用KeyListener的最优方案是结合Swing键绑定(Key Bindings)和文本区域的光标/文本分析:

  • 继承JTextPane,通过键绑定监听Ctrl+Enter组合键——这是Swing官方推荐的组件事件处理方式,比KeyListener更适配文本组件的焦点与事件分发机制;
  • 绑定触发后,获取当前光标位置,向前扫描识别完整的缩写;
  • 匹配预设的缩写映射表,替换对应文本并调整光标位置。

完整实现代码

import javax.swing.*;
import javax.swing.text.BadLocationException;
import java.awt.event.ActionEvent;
import java.util.HashMap;
import java.util.Map;

public class AbbreviationTextPane extends JTextPane {
    // 缩写-替换内容映射表
    private final Map<String, String> abbreviationMap;

    public AbbreviationTextPane() {
        abbreviationMap = new HashMap<>();
        // 初始化示例缩写
        abbreviationMap.put("brb", "Be right back");
        abbreviationMap.put("lol", "Laugh out loud");
        abbreviationMap.put("ty", "Thank you");

        // 绑定Ctrl+Enter组合键
        setupKeyBinding();
    }

    private void setupKeyBinding() {
        // 获取输入映射,使用WHEN_FOCUSED确保组件聚焦时触发
        InputMap inputMap = getInputMap(JComponent.WHEN_FOCUSED);
        ActionMap actionMap = getActionMap();

        // 定义Ctrl+Enter的键Stroke
        KeyStroke ctrlEnter = KeyStroke.getKeyStroke("control ENTER");
        inputMap.put(ctrlEnter, "replaceAbbreviation");
        actionMap.put("replaceAbbreviation", new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                replaceCurrentAbbreviation();
            }
        });
    }

    private void replaceCurrentAbbreviation() {
        int caretPosition = getCaretPosition();
        if (caretPosition == 0) {
            return;
        }

        // 向前扫描,找到当前缩写的起始位置(以非字母数字为边界)
        StringBuilder currentAbbreviation = new StringBuilder();
        try {
            for (int i = caretPosition - 1; i >= 0; i--) {
                char c = getDocument().getText(i, 1).charAt(0);
                if (Character.isLetterOrDigit(c)) {
                    currentAbbreviation.insert(0, c);
                } else {
                    break;
                }
            }
        } catch (BadLocationException ex) {
            ex.printStackTrace();
            return;
        }

        String abbr = currentAbbreviation.toString();
        if (abbreviationMap.containsKey(abbr)) {
            String replacement = abbreviationMap.get(abbr);
            try {
                // 删除原缩写
                getDocument().remove(caretPosition - abbr.length(), abbr.length());
                // 插入替换内容
                getDocument().insertString(caretPosition - abbr.length(), replacement, null);
                // 将光标移动到替换内容末尾
                setCaretPosition(caretPosition - abbr.length() + replacement.length());
            } catch (BadLocationException ex) {
                ex.printStackTrace();
            }
        }
    }

    // 测试主方法
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("Abbreviation TextPane Demo");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(400, 300);

            AbbreviationTextPane textPane = new AbbreviationTextPane();
            textPane.setText("输入缩写后按Ctrl+Enter替换:\nbrb\nlol\nty");
            frame.add(new JScrollPane(textPane));

            frame.setVisible(true);
        });
    }
}

功能演示说明

  1. 运行程序后,在文本框中输入预设的缩写(如brb);
  2. 将光标定位到缩写的末尾(比如输入brb后光标在b后面);
  3. 按下Ctrl+Enter,缩写会立即替换为对应的完整文本(brb→Be right back);
  4. 光标会自动移动到替换后文本的末尾,方便继续输入。

方案优势

  • 采用Swing官方推荐的键绑定,避免了KeyListener的焦点问题(比如组件失焦时不会误触发);
  • 通过文档API直接操作文本,保证了文本修改的原子性和正确性;
  • 缩写映射表可灵活扩展,支持动态添加/删除缩写规则。

内容的提问来源于stack exchange,提问作者Corey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 23:35:20