- Fix window drag: install eventFilter on live2d_container, central, and _live2d_widget; fix super() call in dynamic class - Fix text input: remove WA_TransparentForMouseEvents from _chat_container - Force QT_QPA_PLATFORM=xcb on Linux (wayland has mouse event issues) - Add HealthTracker module, update AgentBrain with health integration - Update scheduler and memory modules - Add v5_modify documentation Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
131 lines
3.9 KiB
Markdown
131 lines
3.9 KiB
Markdown
# v5_modify — 窗口拖拽与文本输入修复
|
||
|
||
## 故障描述
|
||
|
||
1. **窗口无法拖动**:鼠标左键点击并拖动窗口区域时,窗口不跟随移动。
|
||
2. **聊天输入框无法输入文字**:在输入框中点击后无法输入文字。
|
||
|
||
## 环境
|
||
|
||
- 平台:Linux (Fedora 40)
|
||
- Qt 平台:xcb(Wayland 下存在鼠标事件兼容性问题)
|
||
- Python:3.13 + PySide6
|
||
- 桌宠窗口:无边框、置顶、Tool 类型
|
||
|
||
---
|
||
|
||
## 故障 1:窗口拖动失效
|
||
|
||
### 根因分析
|
||
|
||
**问题 A:`super()` 在动态类中调用失败**
|
||
|
||
`PetWindow` 使用 `type()` 动态创建,`eventFilter` 方法中调用 `super().eventFilter()` 在 PySide6 中会导致 `SystemError` 或属性错误。
|
||
|
||
**问题 B:鼠标事件未到达事件过滤器**
|
||
|
||
- `WA_TransparentForMouseEvents` 属性使 `QWebEngineView` 将鼠标事件传递给下层窗口
|
||
- 但 `QWebEngineView` 本身没有安装事件过滤器,所以即使 `live2d_container` 安装了过滤器,`WebEngineView` 仍然先接收并处理了 `MouseButtonPress` 事件
|
||
- 事件类型 `68 (ChildAdded)` 和 `69 (ChildPolished)` 能到达过滤器,但 `MouseButtonPress (2)` 始终没有触发
|
||
|
||
**问题 C:Wayland vs X11 平台差异**
|
||
|
||
`QT_QPA_PLATFORM=wayland` 时 Qt 的鼠标事件分发机制与 `xcb` 不同,导致事件冒泡行为不一致。`xcb` 平台下事件能正常到达过滤器。
|
||
|
||
### 修复方案
|
||
|
||
**1. 修复 `eventFilter` 中的 `super()` 调用**
|
||
|
||
```python
|
||
# 错误 ❌
|
||
return super().eventFilter(obj, event)
|
||
|
||
# 正确 ✅
|
||
return self._QtWidgets.QMainWindow.eventFilter(self, obj, event)
|
||
```
|
||
|
||
**2. 多层事件过滤器安装**
|
||
|
||
在三个层级同时安装事件过滤器:
|
||
|
||
```python
|
||
# _init_ui 中
|
||
live2d_container.installEventFilter(self) # Live2D 容器
|
||
central.installEventFilter(self) # 中央部件
|
||
|
||
# _init_live2d 中
|
||
self._live2d_widget.installEventFilter(self) # Live2D WebEngineView 控件
|
||
```
|
||
|
||
**3. `eventFilter` 中添加 Live2D 控件判断**
|
||
|
||
```python
|
||
is_live2d_target = (hasattr(self, '_live2d_widget')
|
||
and self._live2d_widget is not None
|
||
and obj == self._live2d_widget)
|
||
if obj != live2d_container and obj != self.centralWidget() and not is_live2d_target:
|
||
return self._QtWidgets.QMainWindow.eventFilter(self, obj, event)
|
||
```
|
||
|
||
**4. Qt 平台强制使用 xcb**
|
||
|
||
```python
|
||
# main.py
|
||
if sys.platform.startswith("linux") and os.environ.get("QT_QPA_PLATFORM") is None:
|
||
os.environ["QT_QPA_PLATFORM"] = "xcb" # 而非 wayland
|
||
```
|
||
|
||
**5. 启用 Hover 事件属性**
|
||
|
||
```python
|
||
central.setAttribute(self._QtCore.Qt.WidgetAttribute.WA_Hover)
|
||
```
|
||
|
||
---
|
||
|
||
## 故障 2:聊天输入框无法输入
|
||
|
||
### 根因分析
|
||
|
||
`_chat_container`(包含输入框的部件)错误地设置了 `WA_TransparentForMouseEvents` 属性,导致鼠标事件穿透该部件,下层的 `live2d_container` 接收到事件并触发拖拽流程,输入框无法获得焦点。
|
||
|
||
### 修复方案
|
||
|
||
移除了 `_chat_container` 上的 `WA_TransparentForMouseEvents` 属性,让输入框可以正常接收鼠标事件。
|
||
|
||
```python
|
||
# 已移除此错误设置
|
||
# self._chat_container.setAttribute(self._QtCore.Qt.WidgetAttribute.WA_TransparentForMouseEvents)
|
||
```
|
||
|
||
---
|
||
|
||
## 修改的文件
|
||
|
||
| 文件 | 修改内容 |
|
||
|------|----------|
|
||
| `main.py` | 默认平台改为 `xcb` |
|
||
| `ui/pet_window.py` | 事件过滤器多层安装、修复 `super()` 调用、启用 `WA_Hover` |
|
||
|
||
---
|
||
|
||
## 验证方法
|
||
|
||
```bash
|
||
/home/e2hang/miniforge3/envs/ezvibe/bin/python3 main.py
|
||
```
|
||
|
||
- ✅ 鼠标左键按住 Live2D 区域或窗口主体可拖动窗口
|
||
- ✅ 聊天输入框可正常输入文字
|
||
- ✅ 按钮点击正常
|
||
- ⚠️ Live2D 渲染在 X11 下可能存在 SSL handshake 警告,不影响功能
|
||
|
||
---
|
||
|
||
## 相关技术点
|
||
|
||
- `QMainWindow.eventFilter()` vs `super().eventFilter()` 在动态类中的差异
|
||
- `WA_TransparentForMouseEvents` 与鼠标事件传递
|
||
- Qt 平台插件:`xcb` vs `wayland` 的事件分发差异
|
||
- 多层事件过滤器覆盖:容器 → 中央部件 → 子控件
|