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

IntelliJ系列IDE模态对话框中兼容IME的键盘按键码监听与文本插入实现问题咨询

IntelliJ系列IDE模态对话框中兼容IME的键盘按键码监听与文本插入实现问题咨询

大家好,我现在在开发IntelliJ系列IDE的插件,需求是模态对话框打开时监听键盘输入,按下特定键后插入指定字符串到代码编辑标签页,同时关闭对话框,而且必须兼容所有输入语言(包括非拉丁字符语言)和激活的IME输入法——所以核心是要基于按键码而非输入字符来判断。

我已经写了一段代码,非IME状态下(不管是拉丁还是非拉丁语言)都能正常工作,但一旦激活IME输入法,键盘事件就无法被正确捕获处理了,想请教下怎么修改才能兼容IME模式?

现有代码情况

我的SimpleDialog类核心代码如下:

package com.nnn

import com.intellij.openapi.ui.DialogWrapper
import com.intellij.openapi.editor.Document
import com.intellij.openapi.project.Project
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.ide.ui.LafManager
import com.intellij.openapi.fileEditor.FileEditorManager
import java.awt.event.KeyEvent
import java.awt.Toolkit
import java.awt.KeyboardFocusManager
import java.awt.KeyEventDispatcher
import java.awt.event.InputMethodEvent
import java.awt.event.InputMethodListener
import java.awt.im.InputMethodRequests
import javax.swing.JComponent
import javax.swing.JLabel
import javax.swing.JPanel
import javax.swing.Action
import javax.swing.ImageIcon
import java.awt.Rectangle
import java.awt.font.TextHitInfo
import java.text.AttributedCharacterIterator
import java.text.AttributedString

class SimpleDialog(private val project: Project) : DialogWrapper(true), InputMethodRequests {
    private var textInserted = false
    private var keyProcessed = false

    companion object {
        const val DEFINABLE_TERM = "#[+DefinableTerm--YDID \$END\$]"
        const val IMPORTANT_ENTITY = "#[+ImportantEntity--YDID \$END\$]"
        const val KEYWORD = "#[+Keyword--YDID \$END\$]"
        const val KEYPHRASE = "#[+Keyphrase--YDID \$END\$]"
        const val SECONDARY_ENTITY = "#[+SecondaryEntity--YDID \$END\$]"
        const val TERM = "#[+Term--YDID \$END\$]"
        const val KEYWORD_CONTRAST = "#[+Keyword__Contrast--YDID \$END\$]"
        const val IMPORTANT_ENTITY_CODE = "#[+ImportantEntity__Code--YDID \$END\$]"
        const val SECONDARY_ENTITY_CODE = "#[+SecondaryEntity__Code--YDID \$END\$]"
        const val TERM_CONTRAST = "#[+Term__Contrast--YDID \$END\$]"
    }

    private val keyEventDispatcher = KeyEventDispatcher { keyEvent ->
        println("KeyEventDispatcher: ${ keyEvent.keyCode }, character: ${ keyEvent.keyChar }")
        println(keyEvent.id)
        println(keyEvent.id == KeyEvent.KEY_TYPED)
        println(keyEvent.id == KeyEvent.KEY_PRESSED)

        if (keyEvent.id == KeyEvent.KEY_TYPED || keyEvent.id == KeyEvent.KEY_PRESSED) {
            println("Checkpoint 1")
            onKeyPressed(keyEvent)
        }
        println("Checkpoint 2")
        println("===============================")
        false
    }

    private fun onKeyPressed(keyEvent: KeyEvent) {
        println("onKeyPressed: ${ keyEvent.keyCode }, character: ${ keyEvent.keyChar }")
        if (textInserted) {
            return
        }
        if (keyEvent.isControlDown) {
            handleControlKeyCombinations(keyEvent)
        } else if (keyEvent.id == KeyEvent.KEY_TYPED) {
            handleCharacterInput(keyEvent.keyChar)
        } else if (keyEvent.id == KeyEvent.KEY_PRESSED) {
            handleKeyPress(keyEvent.keyCode)
        }
    }

    override fun show() {
        println("Dialog shown")
        KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(keyEventDispatcher)
        super.show()
    }

    // 省略其他实现方法(如handleControlKeyCombinations、handleCharacterInput等)
}

问题现象

  1. 非IME正常情况:比如按下t键,控制台输出如下,能正常触发onKeyPressed并完成文本插入:
Dialog shown
KeyEventDispatcher: 84, character: t
401
false
true
Checkpoint 1
onKeyPressed: 84, character: t
handleKeyPress: 84
Inserting text: #[+Term--YDID $END$]
Dialog disposed
Checkpoint 2
===============================
  1. IME激活异常情况:同样按下t键,控制台输出显示keyEvent.id既不是KEY_TYPED也不是KEY_PRESSED,导致onKeyPressed完全没被调用:
Dialog shown
KeyEventDispatcher: 84, character: t
402
false
false
Checkpoint 2
===============================

我的初步分析

从输出看,IME激活时捕获到的keyEvent.id是402,对应KeyEvent.KEY_RELEASED,而我的代码只处理了KEY_TYPED和KEY_PRESSED事件。但直接把KEY_RELEASED加入判断的话,会不会和正常的事件流程冲突?或者有没有更适配IME的键盘事件监听方案?

有没有大佬能指点下怎么修改代码,才能在IME激活时也能正确捕获按键码并完成后续的文本插入逻辑?


内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 13:39:30