Qt模块扩展:将Qt虚拟键盘的拼音输入法扩展,支持键盘硬件输入的输入法方法(QtVirtualkeyboard)
QtVirtualkeyboard是一个Qt官方给触摸屏提供的Qt应用专用的 (只支持Qt应用程序唤出)输入法解决方案。他支持中文(拼英、手写、仓吉等)、日文、韩文文字的联想词、自动补全等操作,且中文拼英输入法也比较全面好用,可移植性高。可是没有对物理键盘的输入加以支持,导致在研发过程中,如果某些需要对外接物理键盘进行支持,则需要额外的成本加入第三方输入法,十分麻烦且风险巨大。
在这里介绍一种方法,可以让它支持物理键盘输入。
我先通过修改
QVirtualKeyboardInputContextPrivate::filterEvent 函数,增加新的过滤物理键盘事件的方式。这样我们可以监听得到想要的物理键盘事件,比如它自身就支持的上下左右导航键的代码如下:
#ifdef QT_VIRTUALKEYBOARD_ARROW_KEY_NAVIGATION int key = keyEvent->key(); if ((key >= Qt::Key_Left && key <= Qt::Key_Down) || key == Qt::Key_Return) { if (type == QEvent::KeyPress && platformInputContext->isInputPanelVisible()) { activeNavigationKeys += key; emit navigationKeyPressed(key, keyEvent->isAutoRepeat()); return true; } else if (type == QEvent::KeyRelease && activeNavigationKeys.contains(key)) { activeNavigationKeys -= key; emit navigationKeyReleased(key, keyEvent->isAutoRepeat()); return true; } } #endif
我们可以照搬它的实现,在下面实现一个过滤物理键盘事件的过程
#ifdef QT_VIRTUALKEYBOARD_FILTER_HARDWARE_KEY int keycode = keyEvent->key(); { Q_Q(QVirtualKeyboardInputContext); HKeyState state = (type == QEvent::KeyRelease ? HKeyState::HKeyRelease : HKeyState::HKeyOther); if(state == HKeyState::HKeyOther)state = (type == QEvent::KeyPress ? HKeyState::HKeyPress : HKeyState::HKeyOther); bool reval = (emit q->hardKeyBoardChanged(keycode , state)); return reval; } #else // Break composing text since the virtual keyboard does not support hard keyboard events (! now supperted (●'◡'●)) if (!preeditText.isEmpty()) commit(); #endif
通过自定一个 hardKeyBoardChanged 信号来触发物理键盘信号,再通过修改每个不同输入法reset方法来监听该事件,达到每个不同输入法获取不同键盘事件又不影响其他功能的目的。
比如我修改了pinyininputmethod.cpp的reset
if(inputContext()) { connect(inputContext(), &QVirtualKeyboardInputContext::hardKeyBoardChanged, this, [&](qint32 keycode, qint32 keystate) { Q_D(PinyinInputMethod); if(d->inputMode != QVirtualKeyboardInputEngine::InputMode::Pinyin || !inputContext() || (keycode >= Qt::Key_Left && keycode <= Qt::Key_Down) // nav key ) return false; if(keycode == Qt::Key_Backspace || keycode == Qt::Key_Delete || keycode == Qt::Key_Space) return keyEvent(static_cast<Qt::Key>(keycode), QString(QChar(keycode)).toLower(), Qt::NoModifier ); if( keystate == HKeyRelease ) { d->activeHardwareKeys -= keycode; } else if( keystate == HKeyPress ) { if(!d->activeHardwareKeys.contains(keycode)) { QString text = QString(QChar(keycode)).toLower(); d->activeHardwareKeys += keycode; bool reval = keyEvent(static_cast<Qt::Key>(keycode), text, Qt::NoModifier ); return reval; } } return true; }, Qt::UniqueConnection ); }
这样就可以传递物理键盘的点击事件到输入法代码中,并进行输入法的自动联想词等一系列的处理,达到我们让QtVirtualkeyboard变成一个全功能的输入法的目的了。
根据GPL情况,github地址: