122 lines
5.0 KiB
Markdown
122 lines
5.0 KiB
Markdown
# 2026-04-29 BarcodeEditor 虚拟键盘不可点击问题修复日志
|
||
|
||
## 一、问题背景
|
||
|
||
在 `BarcodeEditor` 中,`lineEditContent` 获取焦点后会正常呼出 `InputMethod` 虚拟键盘,但键盘弹出后,任意按键都无法点击。
|
||
|
||
用户反馈该问题只出现在 `BarcodeEditor` 场景中,而 `InputMethod` 在系统其他页面表现正常。
|
||
|
||
## 二、问题现象
|
||
|
||
- `lineEditContent` 获得焦点后,虚拟键盘可以显示。
|
||
- 虚拟键盘显示后,按钮点击无响应。
|
||
- 同一套输入法在其他页面可以正常输入,说明不是键盘控件本身整体失效。
|
||
|
||
## 三、排查思路
|
||
|
||
本次排查没有只局限在 `BarcodeEditor` 单页,而是沿着“焦点切换 + 全局事件过滤 + 输入法显示/隐藏逻辑”做了整体梳理:
|
||
|
||
1. 检查 `BarcodeEditor.cpp / .h` 中与编辑框及焦点处理相关的逻辑。
|
||
2. 检查 `InputMethod.cpp` 与 `MyInputMethod.cpp` 中虚拟键盘显示、隐藏、发送按键的实现。
|
||
3. 检查全局输入法触发入口,最终定位到 `InkJetPrinter::eventFilter(QObject *, QEvent *)`。
|
||
|
||
排查后确认:
|
||
|
||
- 当前工程通过 `InkJetPrinter::eventFilter()` 统一处理 `FocusIn / FocusOut`,从而控制虚拟键盘显示与隐藏。
|
||
- 若事件处理不区分“点到了输入法自己”还是“点到了其他区域”,就可能出现键盘刚收到点击就被焦点切换或隐藏逻辑打断的问题。
|
||
- 因为工程里已经有全局事件过滤,所以比起只在 `BarcodeEditor` 中单点修复,更适合补齐一套通用的“点击空白处失焦并隐藏键盘,同时点击键盘自身不误隐藏”的机制。
|
||
|
||
## 四、本次修改内容
|
||
|
||
### 1. 修改 `MyInputMethod.cpp`
|
||
|
||
新增头文件:
|
||
|
||
- `#include <QTextEdit>`
|
||
|
||
新增方法:
|
||
|
||
#### `bool MyInputMethod::shouldIgnoreHideForWidget(QWidget *widget) const`
|
||
|
||
作用:
|
||
|
||
- 判断当前点击/聚焦的控件是否属于虚拟键盘本体;
|
||
- 如果是 `inputMethod` 自身、其子控件,或 `digitalInput` 自身、其子控件,则返回 `true`;
|
||
- 同时保留对 `inputPreviewBox` 的排除。
|
||
|
||
这样做的目的,是避免“用户点击虚拟键盘按钮时,程序先把键盘隐藏掉,导致按钮无法真正处理点击”。
|
||
|
||
#### `void MyInputMethod::clearCurrentFocusAndHide()`
|
||
|
||
作用:
|
||
|
||
- 获取当前焦点控件;
|
||
- 如果当前焦点不是输入法本体,则清除其焦点;
|
||
- 隐藏 `inputMethod` 和 `digitalInput`;
|
||
- 调用 `inputMethod->onHiden()` 做隐藏后的清理。
|
||
|
||
这个方法用于统一处理“点击空白区域时关闭输入法”的需求。
|
||
|
||
#### 调整 `updateHandler(int type)`
|
||
|
||
在入口增加:
|
||
|
||
- 如果当前焦点控件属于输入法自己,则直接返回,不再继续执行隐藏/显示逻辑。
|
||
|
||
这一步用于避免输入法自身参与焦点切换时,触发错误的隐藏处理。
|
||
|
||
### 2. 修改 `InkJetPrinter.cpp`
|
||
|
||
修改 `InkJetPrinter::eventFilter(QObject *watched, QEvent *event)`:
|
||
|
||
- 保留原有 `FocusIn / FocusOut` 对输入法的显示隐藏控制;
|
||
- 新增 `QEvent::MouseButtonPress` 处理。
|
||
|
||
新增逻辑如下:
|
||
|
||
- 若当前被点击对象是 `QWidget`;
|
||
- 且它不是 `QSpinBox / QLineEdit / QTextEdit` 这类可编辑输入控件;
|
||
- 且它也不是虚拟键盘本身及其子控件;
|
||
- 则调用 `myInputMethod->clearCurrentFocusAndHide()`。
|
||
|
||
也就是说:
|
||
|
||
- 点击输入框:正常保留焦点,键盘继续可用;
|
||
- 点击虚拟键盘按钮:不会被误判为“点击空白处”,键盘不会先被隐藏;
|
||
- 点击普通空白区域或非编辑控件:输入框失焦,键盘自动收起。
|
||
|
||
## 五、修复结果
|
||
|
||
本次修复后,输入法相关行为被整理为一套更稳定的通用机制:
|
||
|
||
1. 可编辑控件获取焦点时,正常弹出虚拟键盘;
|
||
2. 点击虚拟键盘自身时,不会触发误隐藏;
|
||
3. 点击页面空白区域或普通控件时,会清理当前焦点并隐藏虚拟键盘。
|
||
|
||
这次处理不是“只为 `BarcodeEditor` 打补丁”,而是将该问题在全局输入法交互层做了统一修复,可同时改善其他页面的体验一致性。
|
||
|
||
## 六、验证建议
|
||
|
||
建议至少验证以下场景:
|
||
|
||
### `BarcodeEditor`
|
||
|
||
- 点击 `lineEditContent`,确认虚拟键盘正常弹出;
|
||
- 连续点击虚拟键盘字母、数字、退格、确认等按键,确认可以响应;
|
||
- 点击页面空白区域,确认输入框失焦且键盘隐藏。
|
||
|
||
### 其他页面回归验证
|
||
|
||
- 任意 `QLineEdit` 页面:确认键盘仍可正常呼出和输入;
|
||
- `QSpinBox` 页面:确认数字键盘逻辑未受影响;
|
||
- `QTextEdit` 页面:确认点击输入法按钮仍可输入文本;
|
||
- 点击输入法自身按钮时,不应出现“按下立即消失”或“完全点不动”的现象。
|
||
|
||
## 七、本次会话记录补充
|
||
|
||
在本次对话过程中,除修复“`BarcodeEditor` 弹出键盘但无法点击”问题外,还顺带完成了一项通用交互增强:
|
||
|
||
- **点击空白区域自动失焦并隐藏虚拟键盘**。
|
||
|
||
该增强已通过全局事件过滤接入,而不是局限于某一个编辑器页面,便于后续维护。
|