EG/demo/GUI_FIXES_SUMMARY.md
2025-07-02 09:49:59 +08:00

4.8 KiB
Raw Blame History

GUI 显示问题修复总结

问题描述

test.py 主程序中3D文本和虚拟屏幕能够正常显示但是2D GUI组件按钮、标签、输入框看不见。

问题原因分析

1. 坐标系统不匹配

  • 3D GUI组件3D文本、虚拟屏幕使用世界坐标系统,坐标范围可以是任意值
  • 2D GUI组件(按钮、标签、输入框)使用屏幕坐标系统,坐标范围通常是 -1 到 1

2. 具体问题

原代码中所有GUI组件都使用相同的位置参数 pos=(0, 0, 0)

# 原来的错误代码
button = DirectButton(
    text=text,
    pos=pos,  # 直接使用3D坐标错误
    scale=size,
    # ...
)

当传入像 (5, 0, 0) 这样的3D坐标时

  • 3D组件正常显示在世界坐标 (5, 0, 0)
  • 2D组件会被显示在屏幕坐标 (5, 0, 0),这超出了屏幕范围 [-1, 1],因此不可见

解决方案

1. 坐标转换

为2D GUI组件添加坐标转换逻辑

def createGUIButton(self, pos=(0, 0, 0), text="按钮", size=0.1):
    from direct.gui.DirectGui import DirectButton
    
    # 将3D坐标转换为2D屏幕坐标
    # DirectGUI使用屏幕坐标系范围是-1到1
    gui_pos = (pos[0] * 0.1, 0, pos[2] * 0.1)  # 缩放到合适的屏幕范围
    
    button = DirectButton(
        text=text,
        pos=gui_pos,  # 使用转换后的屏幕坐标
        scale=size,
        # ...
    )

2. 转换规则

  • 输入坐标: 3D逻辑坐标范围 -50 到 50用户友好
  • 输出坐标: 2D屏幕坐标范围 -1 到 1DirectGUI要求
  • 转换公式: 屏幕坐标 = 逻辑坐标 × 0.1

3. 属性面板优化

为了更好地编辑2D GUI组件属性面板中添加了特殊处理

def updateGUIPropertyPanel(self, gui_element):
    gui_type = gui_element.getTag("gui_type")
    
    if gui_type in ["button", "label", "entry"]:
        # 2D GUI组件使用逻辑坐标编辑
        logical_x = pos.getX() / 0.1  # 反向转换为逻辑坐标
        logical_z = pos.getZ() / 0.1
        
        # 提供逻辑坐标编辑界面
        xPos.setValue(logical_x)
        xPos.valueChanged.connect(lambda v: self.editGUI2DPosition(gui_element, "x", v))
        
        # 同时显示实际屏幕坐标(只读)
        actualXLabel = QLabel(f"{pos.getX():.3f}")
    else:
        # 3D GUI组件使用世界坐标编辑
        # 正常的3D坐标编辑逻辑

修复效果验证

1. 测试脚本

创建了两个测试脚本验证修复效果:

  • test_2d_gui_fix.py: 简单的2D GUI显示测试
  • test_gui_complete.py: 完整的GUI功能测试

2. 测试结果

修复后的测试显示:

  • 所有位置的2D按钮都可见且可点击
  • 所有位置的2D标签都正常显示
  • 所有位置的2D输入框都可见且可输入
  • 3D文本和虚拟屏幕继续正常工作
  • 坐标转换计算正确

3. 控制台输出示例

创建了 中心 位置的GUI元素:
  - 按钮位置: (0.0, 0, 0.0)
  - 标签位置: (0.0, 0, -0.2)
  - 输入框位置: (0.0, 0, -0.4)
创建了 左侧 位置的GUI元素:
  - 按钮位置: (-0.5, 0, 0.0)
  - 标签位置: (-0.5, 0, -0.2)
  - 输入框位置: (-0.5, 0, -0.4)

关键改进点

1. 用户体验

  • 用户仍然可以使用直观的"逻辑坐标"(如 -5, 0, 5来指定GUI位置
  • 系统自动处理坐标转换,对用户透明

2. 一致性

  • 3D GUI组件继续使用世界坐标系统
  • 2D GUI组件使用合适的屏幕坐标系统
  • 属性面板根据组件类型提供相应的编辑界面

3. 可维护性

  • 坐标转换逻辑集中在创建方法中
  • 添加了专门的2D GUI位置编辑方法 editGUI2DPosition()
  • 保持了代码结构的清晰性

使用建议

1. 创建2D GUI组件

# 使用逻辑坐标创建(推荐)
button = world.createGUIButton((-5, 0, 0), "左侧按钮")  # 显示在屏幕左侧
button = world.createGUIButton((5, 0, 0), "右侧按钮")   # 显示在屏幕右侧
button = world.createGUIButton((0, 0, 5), "上方按钮")   # 显示在屏幕上方

2. 创建3D GUI组件

# 使用世界坐标创建(不变)
text3d = world.createGUI3DText((0, 5, 2), "3D文本")
screen = world.createGUIVirtualScreen((3, 8, 0), (2, 1), "虚拟屏幕")

3. 坐标范围建议

  • 2D GUI逻辑坐标: -10 到 10对应屏幕范围 -1 到 1
  • 3D GUI世界坐标: 任意合理范围

总结

这次修复解决了2D GUI组件不可见的核心问题通过正确的坐标系统转换确保了

  1. 所有GUI组件都能正常显示
  2. 用户界面保持直观和一致
  3. 编辑功能完全可用
  4. 代码结构保持清晰

修复验证显示所有功能都正常工作用户现在可以在主程序中成功创建和使用所有类型的GUI元素。