338 lines
12 KiB
Python
338 lines
12 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
|
||
"""
|
||
Qt环境渲染修复版本
|
||
解决Qt集成环境中的渲染问题
|
||
"""
|
||
|
||
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.QtOpenGL import QOpenGLWidget
|
||
from direct.showbase.ShowBase import ShowBase
|
||
from direct.gui.DirectGui import *
|
||
from direct.gui.OnscreenText import OnscreenText
|
||
from panda3d.core import *
|
||
import os
|
||
|
||
# 强制配置Panda3D使用OpenGL
|
||
loadPrcFileData("", """
|
||
win-size 800 600
|
||
window-title Qt Fixed Test
|
||
framebuffer-multisample 1
|
||
multisamples 2
|
||
prefer-parasite-buffer false
|
||
""")
|
||
|
||
class QtFixedWorld(ShowBase):
|
||
def __init__(self):
|
||
ShowBase.__init__(self)
|
||
|
||
print("=== Qt修复版本世界初始化 ===")
|
||
|
||
# 设置背景色
|
||
self.setBackgroundColor(0.2, 0.2, 0.3)
|
||
print("背景色设置完成")
|
||
|
||
# 调整相机位置
|
||
self.cam.setPos(0, -10, 5)
|
||
self.cam.lookAt(0, 0, 0)
|
||
|
||
# 检查基本状态
|
||
print(f"窗口类型: {type(self.win)}")
|
||
print(f"图形引擎: {self.graphicsEngine}")
|
||
print(f"窗口大小: {self.win.getXSize()} x {self.win.getYSize()}")
|
||
|
||
# 初始化GUI元素列表
|
||
self.gui_elements = []
|
||
|
||
# 尝试加载中文字体
|
||
try:
|
||
self.chinese_font = self.loader.loadFont('/usr/share/fonts/truetype/wqy/wqy-microhei.ttc')
|
||
if not self.chinese_font:
|
||
print("警告: 无法加载中文字体,将使用默认字体")
|
||
except:
|
||
print("警告: 无法加载中文字体,将使用默认字体")
|
||
self.chinese_font = None
|
||
|
||
# 创建测试内容
|
||
self.createTestContent()
|
||
|
||
# 延迟创建GUI元素
|
||
self.taskMgr.doMethodLater(0.5, self.createGUIElements, "create-gui")
|
||
|
||
def createTestContent(self):
|
||
"""创建测试内容"""
|
||
print("\n--- 创建测试内容 ---")
|
||
|
||
# 创建3D几何体
|
||
from panda3d.core import CardMaker
|
||
cm = CardMaker("test-plane")
|
||
cm.setFrame(-2, 2, -2, 2)
|
||
|
||
self.testPlane = self.render.attachNewNode(cm.generate())
|
||
self.testPlane.setPos(0, 5, 0)
|
||
self.testPlane.setColor(0.8, 0.2, 0.2, 1) # 红色
|
||
|
||
# 创建3D文本
|
||
textNode = TextNode('3d-text')
|
||
textNode.setText("3D Test Content")
|
||
textNode.setAlign(TextNode.ACenter)
|
||
if self.chinese_font:
|
||
textNode.setFont(self.chinese_font)
|
||
|
||
self.text3D = self.render.attachNewNode(textNode)
|
||
self.text3D.setPos(0, 3, 2)
|
||
self.text3D.setScale(0.5)
|
||
self.text3D.setColor(1, 1, 0, 1)
|
||
self.text3D.setBillboardAxis()
|
||
|
||
# 添加光照
|
||
alight = AmbientLight('alight')
|
||
alight.setColor((0.3, 0.3, 0.3, 1))
|
||
alnp = self.render.attachNewNode(alight)
|
||
self.render.setLight(alnp)
|
||
|
||
dlight = DirectionalLight('dlight')
|
||
dlight.setColor((0.8, 0.8, 0.8, 1))
|
||
dlnp = self.render.attachNewNode(dlight)
|
||
dlnp.setHpr(45, -45, 0)
|
||
self.render.setLight(dlnp)
|
||
|
||
print("3D内容创建完成")
|
||
|
||
def createGUIElements(self, task=None):
|
||
"""创建GUI元素"""
|
||
print("\n--- 创建GUI元素 ---")
|
||
|
||
# 创建屏幕标题
|
||
self.title = OnscreenText(
|
||
text="Qt环境修复测试",
|
||
pos=(0, 0.9),
|
||
scale=0.08,
|
||
fg=(1, 1, 1, 1),
|
||
align=TextNode.ACenter,
|
||
font=self.chinese_font if self.chinese_font else None
|
||
)
|
||
print("屏幕标题创建完成")
|
||
|
||
# 测试主程序中的GUI创建方法
|
||
try:
|
||
# 按钮测试
|
||
self.button1 = self.createGUIButton((0, 0, 0), "中心按钮", 0.08)
|
||
self.button2 = self.createGUIButton((-10, 0, 0), "左按钮", 0.08)
|
||
self.button3 = self.createGUIButton((10, 0, 0), "右按钮", 0.08)
|
||
|
||
# 标签测试
|
||
self.label1 = self.createGUILabel((0, 0, -10), "测试标签", 0.06)
|
||
self.label2 = self.createGUILabel((-10, 0, -5), "左标签", 0.06)
|
||
|
||
# 输入框测试
|
||
self.entry1 = self.createGUIEntry((10, 0, -5), "输入框", 0.05)
|
||
|
||
# 3D文本测试
|
||
self.text3d1 = self.createGUI3DText((0, 5, 3), "3D文本测试", 0.5)
|
||
self.text3d2 = self.createGUI3DText((-3, 3, 1), "左3D文本", 0.3)
|
||
|
||
# 虚拟屏幕测试
|
||
self.screen1 = self.createGUIVirtualScreen((3, 8, 0), (2, 1), "虚拟屏幕")
|
||
|
||
print(f"GUI创建完成,总计: {len(self.gui_elements)} 个元素")
|
||
|
||
except Exception as e:
|
||
print(f"GUI创建失败: {str(e)}")
|
||
|
||
return task.done if task else None
|
||
|
||
# 复制主程序中的GUI创建方法
|
||
def createGUIButton(self, pos=(0, 0, 0), text="按钮", size=0.1):
|
||
"""创建2D GUI按钮"""
|
||
# 将3D坐标转换为2D屏幕坐标
|
||
gui_pos = (pos[0] * 0.1, 0, pos[2] * 0.1)
|
||
|
||
button = DirectButton(
|
||
text=text,
|
||
pos=gui_pos,
|
||
scale=size,
|
||
command=self.onGUIButtonClick,
|
||
extraArgs=[f"button_{len(self.gui_elements)}"],
|
||
frameColor=(0.2, 0.6, 0.8, 1),
|
||
text_font=self.chinese_font if self.chinese_font else None,
|
||
rolloverSound=None,
|
||
clickSound=None
|
||
)
|
||
|
||
button.setTag("gui_type", "button")
|
||
button.setTag("gui_id", f"button_{len(self.gui_elements)}")
|
||
button.setTag("gui_text", text)
|
||
|
||
self.gui_elements.append(button)
|
||
print(f"创建GUI按钮: {text} 在屏幕位置 {gui_pos}")
|
||
return button
|
||
|
||
def createGUILabel(self, pos=(0, 0, 0), text="标签", size=0.08):
|
||
"""创建2D GUI标签"""
|
||
gui_pos = (pos[0] * 0.1, 0, pos[2] * 0.1)
|
||
|
||
label = DirectLabel(
|
||
text=text,
|
||
pos=gui_pos,
|
||
scale=size,
|
||
frameColor=(0, 0, 0, 0),
|
||
text_fg=(1, 1, 1, 1),
|
||
text_font=self.chinese_font if self.chinese_font else None
|
||
)
|
||
|
||
label.setTag("gui_type", "label")
|
||
label.setTag("gui_id", f"label_{len(self.gui_elements)}")
|
||
label.setTag("gui_text", text)
|
||
|
||
self.gui_elements.append(label)
|
||
print(f"创建GUI标签: {text} 在屏幕位置 {gui_pos}")
|
||
return label
|
||
|
||
def createGUIEntry(self, pos=(0, 0, 0), placeholder="输入文本...", size=0.08):
|
||
"""创建2D GUI文本输入框"""
|
||
gui_pos = (pos[0] * 0.1, 0, pos[2] * 0.1)
|
||
|
||
entry = DirectEntry(
|
||
text="",
|
||
pos=gui_pos,
|
||
scale=size,
|
||
command=self.onGUIEntrySubmit,
|
||
extraArgs=[f"entry_{len(self.gui_elements)}"],
|
||
initialText=placeholder,
|
||
numLines=1,
|
||
width=12,
|
||
focus=0
|
||
)
|
||
|
||
entry.setTag("gui_type", "entry")
|
||
entry.setTag("gui_id", f"entry_{len(self.gui_elements)}")
|
||
entry.setTag("gui_placeholder", placeholder)
|
||
|
||
self.gui_elements.append(entry)
|
||
print(f"创建GUI输入框: {placeholder} 在屏幕位置 {gui_pos}")
|
||
return entry
|
||
|
||
def createGUI3DText(self, pos=(0, 0, 0), text="3D文本", size=0.5):
|
||
"""创建3D空间文本"""
|
||
textNode = TextNode(f'3d-text-{len(self.gui_elements)}')
|
||
textNode.setText(text)
|
||
textNode.setAlign(TextNode.ACenter)
|
||
if self.chinese_font:
|
||
textNode.setFont(self.chinese_font)
|
||
|
||
textNodePath = self.render.attachNewNode(textNode)
|
||
textNodePath.setPos(*pos)
|
||
textNodePath.setScale(size)
|
||
textNodePath.setColor(1, 1, 0, 1)
|
||
textNodePath.setBillboardAxis()
|
||
|
||
textNodePath.setTag("gui_type", "3d_text")
|
||
textNodePath.setTag("gui_id", f"3d_text_{len(self.gui_elements)}")
|
||
textNodePath.setTag("gui_text", text)
|
||
|
||
self.gui_elements.append(textNodePath)
|
||
print(f"创建3D文本: {text} 在世界位置 {pos}")
|
||
return textNodePath
|
||
|
||
def createGUIVirtualScreen(self, pos=(0, 0, 0), size=(2, 1), text="虚拟屏幕"):
|
||
"""创建3D虚拟屏幕"""
|
||
cm = CardMaker(f"virtual-screen-{len(self.gui_elements)}")
|
||
cm.setFrame(-size[0]/2, size[0]/2, -size[1]/2, size[1]/2)
|
||
virtualScreen = self.render.attachNewNode(cm.generate())
|
||
virtualScreen.setPos(*pos)
|
||
virtualScreen.setColor(0.2, 0.2, 0.2, 0.8)
|
||
virtualScreen.setTransparency(TransparencyAttrib.MAlpha)
|
||
|
||
screenText = TextNode(f'screen-text-{len(self.gui_elements)}')
|
||
screenText.setText(text)
|
||
screenText.setAlign(TextNode.ACenter)
|
||
if self.chinese_font:
|
||
screenText.setFont(self.chinese_font)
|
||
screenTextNP = virtualScreen.attachNewNode(screenText)
|
||
screenTextNP.setPos(0, 0.01, 0)
|
||
screenTextNP.setScale(0.3)
|
||
screenTextNP.setColor(0, 1, 0, 1)
|
||
|
||
virtualScreen.setTag("gui_type", "virtual_screen")
|
||
virtualScreen.setTag("gui_id", f"virtual_screen_{len(self.gui_elements)}")
|
||
virtualScreen.setTag("gui_text", text)
|
||
|
||
self.gui_elements.append(virtualScreen)
|
||
print(f"创建虚拟屏幕: {text} 在世界位置 {pos}")
|
||
return virtualScreen
|
||
|
||
def onGUIButtonClick(self, button_id):
|
||
"""GUI按钮点击事件处理"""
|
||
print(f"✓ GUI按钮被点击: {button_id}")
|
||
|
||
def onGUIEntrySubmit(self, text, entry_id):
|
||
"""GUI输入框提交事件处理"""
|
||
print(f"✓ GUI输入框提交: {entry_id} = {text}")
|
||
|
||
class QtFixedWidget(QOpenGLWidget):
|
||
"""使用QOpenGLWidget的Panda3D部件"""
|
||
def __init__(self, world, parent=None):
|
||
super().__init__(parent)
|
||
self.world = world
|
||
self.setMinimumSize(800, 600)
|
||
print("Qt OpenGL部件创建完成")
|
||
|
||
def paintGL(self):
|
||
"""OpenGL绘制函数"""
|
||
if self.world and hasattr(self.world, 'graphicsEngine'):
|
||
self.world.graphicsEngine.renderFrame()
|
||
|
||
def main():
|
||
"""主函数"""
|
||
print("启动Qt环境修复测试...")
|
||
|
||
app = QApplication(sys.argv)
|
||
|
||
# 创建主窗口
|
||
mainWindow = QMainWindow()
|
||
mainWindow.setWindowTitle("Qt环境修复测试")
|
||
mainWindow.setGeometry(100, 100, 800, 600)
|
||
|
||
# 创建布局和容器
|
||
centralWidget = QWidget()
|
||
layout = QVBoxLayout(centralWidget)
|
||
|
||
# 添加状态标签
|
||
statusLabel = QLabel("Qt环境修复测试 - 应该能看到GUI元素")
|
||
statusLabel.setAlignment(Qt.AlignCenter)
|
||
statusLabel.setStyleSheet("background-color: lightgreen; padding: 10px; color: black;")
|
||
layout.addWidget(statusLabel)
|
||
|
||
# 创建修复版本的世界
|
||
world = QtFixedWorld()
|
||
|
||
# 创建OpenGL部件
|
||
openglWidget = QtFixedWidget(world)
|
||
layout.addWidget(openglWidget)
|
||
|
||
mainWindow.setCentralWidget(centralWidget)
|
||
|
||
# 显示窗口
|
||
mainWindow.show()
|
||
|
||
print("修复版本窗口已显示")
|
||
print("应该能看到:")
|
||
print("- 红色的3D平面")
|
||
print("- 黄色的3D文本")
|
||
print("- 多个2D GUI按钮(蓝色)")
|
||
print("- 2D GUI标签(白色文字)")
|
||
print("- 2D GUI输入框")
|
||
print("- 3D虚拟屏幕")
|
||
|
||
# 运行应用
|
||
return app.exec_()
|
||
|
||
if __name__ == "__main__":
|
||
exit_code = main() |