EG/demo/test_qt_gui_fix.py
2025-12-12 16:16:15 +08:00

259 lines
9.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Qt环境GUI事件修复测试
解决Qt集成环境中DirectGUI事件处理问题
"""
import warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QLabel
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QMouseEvent
from QMeta3D.QMeta3DWidget import QMeta3DWidget
from QMeta3D.Meta3DWorld import Meta3DWorld
from direct.gui.DirectGui import *
from direct.gui.OnscreenText import OnscreenText
from panda3d.core import *
class QtGUIFixWorld(Meta3DWorld):
def __init__(self):
super().__init__()
print("=== Qt GUI事件修复测试 ===")
self.setBackgroundColor(0.2, 0.2, 0.3)
# 检查环境
print(f"窗口类型: {type(self.win)}")
print(f"图形引擎: {self.graphicsEngine}")
# 延迟创建GUI
self.taskMgr.doMethodLater(0.5, self.createTestGUI, "create-gui")
# 保存GUI元素引用用于事件处理
self.gui_elements = []
def createTestGUI(self, task=None):
"""创建测试GUI"""
print("\n--- 创建Qt环境GUI ---")
# 方法1: 标准DirectGUI创建
try:
self.title = OnscreenText(
text="Qt环境GUI测试",
pos=(0, 0.8),
scale=0.08,
fg=(1, 1, 1, 1),
align=TextNode.ACenter
)
print(f"✓ 标题创建成功: {self.title}")
except Exception as e:
print(f"❌ 标题创建失败: {str(e)}")
# 测试按钮1 - 标准创建
try:
self.button1 = DirectButton(
text="标准按钮",
pos=(0, 0, 0.4),
scale=0.1,
frameColor=(0, 1, 0, 1),
command=self.onButton1Click
)
self.gui_elements.append(('button1', self.button1))
print(f"✓ 标准按钮创建成功: {self.button1}")
except Exception as e:
print(f"❌ 标准按钮创建失败: {str(e)}")
# 测试按钮2 - 手动事件处理
try:
self.button2 = DirectButton(
text="修复按钮",
pos=(0, 0, 0.1),
scale=0.1,
frameColor=(1, 0, 0, 1),
command=self.onButton2Click
)
# 手动设置事件处理
self.setupManualEvents(self.button2)
self.gui_elements.append(('button2', self.button2))
print(f"✓ 修复按钮创建成功: {self.button2}")
except Exception as e:
print(f"❌ 修复按钮创建失败: {str(e)}")
# 测试按钮3 - 自定义点击检测
try:
self.button3 = DirectButton(
text="自检按钮",
pos=(0, 0, -0.2),
scale=0.1,
frameColor=(0, 0, 1, 1),
# 不设置command使用自定义检测
)
self.gui_elements.append(('button3', self.button3))
print(f"✓ 自检按钮创建成功: {self.button3}")
# 启动自定义点击检测
self.taskMgr.add(self.checkButtonClicks, "check-clicks")
except Exception as e:
print(f"❌ 自检按钮创建失败: {str(e)}")
return task.done if task else None
def setupManualEvents(self, button):
"""为按钮设置手动事件处理"""
try:
# 获取按钮的PGItem
if hasattr(button, 'guiItem'):
pgItem = button.guiItem
# 强制启用事件
pgItem.setActive(True)
print(f" 手动启用按钮事件: {pgItem}")
except Exception as e:
print(f" 手动事件设置失败: {str(e)}")
def checkButtonClicks(self, task):
"""自定义按钮点击检测"""
# 检查鼠标状态
if hasattr(self, 'mouseWatcherNode') and self.mouseWatcherNode.hasMouse():
# 获取鼠标位置
mouseX = self.mouseWatcherNode.getMouseX()
mouseY = self.mouseWatcherNode.getMouseY()
# 检查是否在button3范围内
if hasattr(self, 'button3'):
buttonPos = self.button3.getPos()
buttonScale = self.button3.getScale()
# 简单的边界检测
if (abs(mouseX - buttonPos.getX()) < buttonScale.getX() * 0.5 and
abs(mouseY - buttonPos.getZ()) < buttonScale.getZ() * 0.5):
# 检查是否有鼠标点击
if self.mouseWatcherNode.isButtonDown('button1'):
self.onButton3Click()
# 防止重复触发
return task.pause(0.5)
return task.cont
def onButton1Click(self):
"""标准按钮点击"""
print("🟢 标准按钮被点击!")
def onButton2Click(self):
"""修复按钮点击"""
print("🔴 修复按钮被点击!")
def onButton3Click(self):
"""自检按钮点击"""
print("🔵 自检按钮被点击!")
def handleQtMouseEvent(self, event):
"""处理Qt鼠标事件"""
try:
# 将Qt事件转换为Panda3D坐标
if hasattr(self, 'win'):
winX = event.x()
winY = event.y()
winWidth = self.win.getXSize()
winHeight = self.win.getYSize()
# 转换为归一化坐标 (-1 到 1)
normalizedX = (winX / winWidth) * 2.0 - 1.0
normalizedY = 1.0 - (winY / winHeight) * 2.0
print(f"Qt鼠标事件: ({winX}, {winY}) -> 归一化: ({normalizedX:.3f}, {normalizedY:.3f})")
# 手动检查GUI元素
for name, element in self.gui_elements:
if hasattr(element, 'getPos'):
elemPos = element.getPos()
elemScale = element.getScale()
# 简单边界检测
if (abs(normalizedX - elemPos.getX()) < elemScale.getX() * 0.5 and
abs(normalizedY - elemPos.getZ()) < elemScale.getZ() * 0.5):
print(f" 点击在 {name} 范围内!")
# 手动触发回调
if name == 'button1':
self.onButton1Click()
elif name == 'button2':
self.onButton2Click()
elif name == 'button3':
self.onButton3Click()
return True
except Exception as e:
print(f"Qt事件处理失败: {str(e)}")
return False
class CustomQMeta3DWidget(QMeta3DWidget):
"""自定义QPanda3DWidget支持事件转发"""
def __init__(self, world, parent=None):
super().__init__(world, parent)
self.world = world
print("自定义QPanda3D部件初始化")
def mousePressEvent(self, event):
"""重写鼠标按下事件"""
print(f"\n=== Qt鼠标按下事件 ===")
print(f"位置: ({event.x()}, {event.y()})")
print(f"按钮: {event.button()}")
# 尝试让世界处理事件
if hasattr(self.world, 'handleQtMouseEvent'):
handled = self.world.handleQtMouseEvent(event)
if handled:
print("事件已被世界处理")
return
# 调用父类方法
super().mousePressEvent(event)
def main():
print("启动Qt环境GUI事件修复测试...")
app = QApplication(sys.argv)
# 创建主窗口
mainWindow = QMainWindow()
mainWindow.setWindowTitle("Qt GUI事件修复测试")
mainWindow.setGeometry(100, 100, 800, 600)
# 创建布局
centralWidget = QWidget()
layout = QVBoxLayout(centralWidget)
# 添加说明
label = QLabel("Qt环境DirectGUI事件修复测试")
label.setAlignment(Qt.AlignCenter)
label.setStyleSheet("background-color: lightgreen; padding: 10px;")
layout.addWidget(label)
# 创建世界
world = QtGUIFixWorld()
# 创建自定义Panda3D部件
pandaWidget = CustomQMeta3DWidget(world)
layout.addWidget(pandaWidget)
mainWindow.setCentralWidget(centralWidget)
mainWindow.show()
print("\n测试说明:")
print("绿色按钮: 标准DirectGUI事件处理")
print("红色按钮: 手动事件修复")
print("蓝色按钮: 自定义点击检测")
print("查看控制台输出了解事件处理情况")
return app.exec_()
if __name__ == "__main__":
main()