259 lines
9.0 KiB
Python
259 lines
9.0 KiB
Python
#!/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 QPanda3D.QPanda3DWidget import QPanda3DWidget
|
||
from QPanda3D.Panda3DWorld import Panda3DWorld
|
||
from direct.gui.DirectGui import *
|
||
from direct.gui.OnscreenText import OnscreenText
|
||
from panda3d.core import *
|
||
|
||
class QtGUIFixWorld(Panda3DWorld):
|
||
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 CustomQPanda3DWidget(QPanda3DWidget):
|
||
"""自定义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 = CustomQPanda3DWidget(world)
|
||
layout.addWidget(pandaWidget)
|
||
|
||
mainWindow.setCentralWidget(centralWidget)
|
||
mainWindow.show()
|
||
|
||
print("\n测试说明:")
|
||
print("绿色按钮: 标准DirectGUI事件处理")
|
||
print("红色按钮: 手动事件修复")
|
||
print("蓝色按钮: 自定义点击检测")
|
||
print("查看控制台输出了解事件处理情况")
|
||
|
||
return app.exec_()
|
||
|
||
if __name__ == "__main__":
|
||
main() |