358 lines
11 KiB
Python
358 lines
11 KiB
Python
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
"""
|
|
PANDA3D GUI功能测试示例
|
|
展示DirectGUI系统的各种组件使用方法
|
|
"""
|
|
|
|
import sys
|
|
from direct.showbase.ShowBase import ShowBase
|
|
from direct.gui.DirectGui import *
|
|
from direct.gui.OnscreenText import OnscreenText
|
|
from direct.gui.OnscreenImage import OnscreenImage
|
|
from panda3d.core import *
|
|
|
|
class GUITestApp(ShowBase):
|
|
def __init__(self):
|
|
ShowBase.__init__(self)
|
|
|
|
# 设置窗口标题
|
|
wp = WindowProperties()
|
|
wp.setTitle("PANDA3D GUI功能测试")
|
|
self.win.requestProperties(wp)
|
|
|
|
# 设置背景颜色
|
|
self.setBackgroundColor(0.2, 0.3, 0.5)
|
|
|
|
# 尝试加载中文字体
|
|
self.chinese_font = self.loadChineseFont()
|
|
|
|
# 创建标题文本
|
|
self.title = OnscreenText(
|
|
text="PANDA3D DirectGUI 组件示例",
|
|
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
|
|
)
|
|
|
|
# 创建各种GUI组件
|
|
self.createButtons()
|
|
self.createLabels()
|
|
self.createEntries()
|
|
self.createSliders()
|
|
self.createCheckboxes()
|
|
self.createRadioButtons()
|
|
self.createScrolledFrame()
|
|
self.createOptionMenu()
|
|
|
|
# 状态显示文本
|
|
self.statusText = OnscreenText(
|
|
text="状态: 准备就绪",
|
|
pos=(-1.2, -0.9),
|
|
scale=0.05,
|
|
fg=(0, 1, 0, 1),
|
|
align=TextNode.ALeft
|
|
)
|
|
|
|
print("GUI测试应用启动成功!")
|
|
print(f"中文字体加载状态: {'成功' if self.chinese_font else '失败,使用默认字体'}")
|
|
print("尝试点击各种GUI组件来测试功能")
|
|
|
|
def loadChineseFont(self):
|
|
"""尝试加载中文字体"""
|
|
import os
|
|
font_paths = [
|
|
'/usr/share/fonts/truetype/wqy/wqy-microhei.ttc',
|
|
'/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc',
|
|
'/usr/share/fonts/truetype/arphic/ukai.ttc',
|
|
'/usr/share/fonts/truetype/arphic/uming.ttc',
|
|
]
|
|
|
|
for font_path in font_paths:
|
|
if os.path.exists(font_path):
|
|
try:
|
|
font = self.loader.loadFont(font_path)
|
|
if font:
|
|
return font
|
|
except:
|
|
continue
|
|
return None
|
|
|
|
def createButtons(self):
|
|
"""创建按钮组件"""
|
|
# 普通按钮
|
|
self.button1 = DirectButton(
|
|
text="普通按钮",
|
|
pos=(-0.8, 0, 0.6),
|
|
scale=0.06,
|
|
command=self.onButton1Click,
|
|
rolloverSound=None,
|
|
clickSound=None,
|
|
text_font=self.chinese_font if self.chinese_font else None
|
|
)
|
|
|
|
# 带图像的按钮
|
|
self.button2 = DirectButton(
|
|
text="彩色按钮",
|
|
pos=(-0.4, 0, 0.6),
|
|
scale=0.06,
|
|
command=self.onButton2Click,
|
|
frameColor=(0.2, 0.8, 0.2, 1),
|
|
rolloverSound=None,
|
|
clickSound=None,
|
|
text_font=self.chinese_font if self.chinese_font else None
|
|
)
|
|
|
|
# 退出按钮
|
|
self.exitButton = DirectButton(
|
|
text="退出程序",
|
|
pos=(0.8, 0, 0.6),
|
|
scale=0.06,
|
|
command=self.exitApp,
|
|
frameColor=(0.8, 0.2, 0.2, 1),
|
|
rolloverSound=None,
|
|
clickSound=None,
|
|
text_font=self.chinese_font if self.chinese_font else None
|
|
)
|
|
|
|
def createLabels(self):
|
|
"""创建标签组件"""
|
|
self.label1 = DirectLabel(
|
|
text="这是一个标签",
|
|
pos=(-0.8, 0, 0.4),
|
|
scale=0.05,
|
|
frameColor=(0, 0, 0, 0), # 透明背景
|
|
text_fg=(1, 1, 0, 1),
|
|
text_font=self.chinese_font if self.chinese_font else None
|
|
)
|
|
|
|
self.label2 = DirectLabel(
|
|
text="带背景的标签",
|
|
pos=(-0.4, 0, 0.4),
|
|
scale=0.05,
|
|
frameColor=(0.3, 0.3, 0.7, 0.8),
|
|
text_fg=(1, 1, 1, 1),
|
|
text_font=self.chinese_font if self.chinese_font else None
|
|
)
|
|
|
|
def createEntries(self):
|
|
"""创建文本输入框"""
|
|
# 普通输入框
|
|
self.entry1 = DirectEntry(
|
|
text="",
|
|
pos=(-0.8, 0, 0.2),
|
|
scale=0.05,
|
|
command=self.onEntry1Submit,
|
|
initialText="在这里输入文本...",
|
|
numLines=1,
|
|
focus=0,
|
|
width=12
|
|
)
|
|
|
|
# 密码输入框
|
|
self.entry2 = DirectEntry(
|
|
text="",
|
|
pos=(-0.4, 0, 0.2),
|
|
scale=0.05,
|
|
command=self.onEntry2Submit,
|
|
initialText="密码输入框",
|
|
numLines=1,
|
|
focus=0,
|
|
width=12,
|
|
obscured=1 # 密码模式
|
|
)
|
|
|
|
def createSliders(self):
|
|
"""创建滑块组件"""
|
|
# 水平滑块
|
|
self.slider1 = DirectSlider(
|
|
range=(0, 100),
|
|
value=50,
|
|
pos=(0.2, 0, 0.4),
|
|
scale=0.4,
|
|
command=self.onSlider1Change,
|
|
orientation=DGG.HORIZONTAL
|
|
)
|
|
|
|
# 垂直滑块
|
|
self.slider2 = DirectSlider(
|
|
range=(0, 100),
|
|
value=25,
|
|
pos=(0.6, 0, 0.2),
|
|
scale=0.3,
|
|
command=self.onSlider2Change,
|
|
orientation=DGG.VERTICAL
|
|
)
|
|
|
|
# 滑块值显示
|
|
self.sliderValueText = OnscreenText(
|
|
text="滑块值: H=50, V=25",
|
|
pos=(0.4, 0.1),
|
|
scale=0.04,
|
|
fg=(1, 1, 1, 1),
|
|
font=self.chinese_font if self.chinese_font else None
|
|
)
|
|
|
|
def createCheckboxes(self):
|
|
"""创建复选框"""
|
|
self.checkbox1 = DirectCheckButton(
|
|
text="选项 1",
|
|
pos=(-0.8, 0, 0),
|
|
scale=0.05,
|
|
command=self.onCheckbox1Toggle,
|
|
rolloverSound=None,
|
|
clickSound=None,
|
|
text_font=self.chinese_font if self.chinese_font else None
|
|
)
|
|
|
|
self.checkbox2 = DirectCheckButton(
|
|
text="选项 2",
|
|
pos=(-0.4, 0, 0),
|
|
scale=0.05,
|
|
command=self.onCheckbox2Toggle,
|
|
rolloverSound=None,
|
|
clickSound=None,
|
|
text_font=self.chinese_font if self.chinese_font else None
|
|
)
|
|
|
|
def createRadioButtons(self):
|
|
"""创建单选按钮组"""
|
|
self.radioButtons = []
|
|
self.radioVar = [0] # 用列表来存储选中的索引
|
|
|
|
for i in range(3):
|
|
radio = DirectRadioButton(
|
|
text=f"单选 {i+1}",
|
|
pos=(-0.8 + i*0.2, 0, -0.2),
|
|
scale=0.05,
|
|
variable=self.radioVar,
|
|
value=[i],
|
|
command=self.onRadioButtonSelect,
|
|
extraArgs=[i], # 添加额外参数
|
|
rolloverSound=None,
|
|
clickSound=None,
|
|
text_font=self.chinese_font if self.chinese_font else None
|
|
)
|
|
self.radioButtons.append(radio)
|
|
|
|
def createScrolledFrame(self):
|
|
"""创建滚动框架"""
|
|
# 创建滚动框架
|
|
self.scrollFrame = DirectScrolledFrame(
|
|
frameSize=(-0.5, 0.5, -0.3, 0.3),
|
|
canvasSize=(-0.5, 0.5, -1, 1),
|
|
pos=(0.2, 0, -0.2),
|
|
frameColor=(0.2, 0.2, 0.2, 0.8),
|
|
scrollBarWidth=0.04,
|
|
verticalScroll_relief=DGG.SUNKEN,
|
|
horizontalScroll_relief=DGG.SUNKEN
|
|
)
|
|
|
|
# 在滚动框架中添加内容
|
|
for i in range(10):
|
|
label = DirectLabel(
|
|
text=f"滚动项目 {i+1}",
|
|
pos=(0, 0, 0.8 - i*0.15),
|
|
scale=0.04,
|
|
parent=self.scrollFrame.getCanvas(),
|
|
frameColor=(0, 0, 0, 0),
|
|
text_fg=(1, 1, 1, 1),
|
|
text_font=self.chinese_font if self.chinese_font else None
|
|
)
|
|
|
|
def createOptionMenu(self):
|
|
"""创建选项菜单"""
|
|
items = ["选项A", "选项B", "选项C", "选项D"]
|
|
self.optionMenu = DirectOptionMenu(
|
|
text="选择选项",
|
|
pos=(0.6, 0, 0),
|
|
scale=0.05,
|
|
items=items,
|
|
initialitem=0,
|
|
command=self.onOptionMenuSelect,
|
|
rolloverSound=None,
|
|
clickSound=None,
|
|
text_font=self.chinese_font if self.chinese_font else None
|
|
)
|
|
|
|
# 事件处理函数
|
|
def onButton1Click(self):
|
|
"""按钮1点击事件"""
|
|
self.updateStatus("普通按钮被点击!")
|
|
print("普通按钮被点击")
|
|
|
|
def onButton2Click(self):
|
|
"""按钮2点击事件"""
|
|
self.updateStatus("彩色按钮被点击!")
|
|
print("彩色按钮被点击")
|
|
|
|
def onEntry1Submit(self, text):
|
|
"""文本输入框提交事件"""
|
|
self.updateStatus(f"输入的文本: {text}")
|
|
print(f"输入的文本: {text}")
|
|
|
|
def onEntry2Submit(self, text):
|
|
"""密码输入框提交事件"""
|
|
self.updateStatus(f"输入的密码长度: {len(text)}")
|
|
print(f"输入的密码: {text}")
|
|
|
|
def onSlider1Change(self):
|
|
"""水平滑块变化事件"""
|
|
value = self.slider1['value']
|
|
self.updateSliderValues()
|
|
print(f"水平滑块值: {value}")
|
|
|
|
def onSlider2Change(self):
|
|
"""垂直滑块变化事件"""
|
|
value = self.slider2['value']
|
|
self.updateSliderValues()
|
|
print(f"垂直滑块值: {value}")
|
|
|
|
def updateSliderValues(self):
|
|
"""更新滑块值显示"""
|
|
h_val = int(self.slider1['value'])
|
|
v_val = int(self.slider2['value'])
|
|
self.sliderValueText.setText(f"滑块值: H={h_val}, V={v_val}")
|
|
|
|
def onCheckbox1Toggle(self, status):
|
|
"""复选框1切换事件"""
|
|
state = "选中" if status else "未选中"
|
|
self.updateStatus(f"复选框1: {state}")
|
|
print(f"复选框1: {state}")
|
|
|
|
def onCheckbox2Toggle(self, status):
|
|
"""复选框2切换事件"""
|
|
state = "选中" if status else "未选中"
|
|
self.updateStatus(f"复选框2: {state}")
|
|
print(f"复选框2: {state}")
|
|
|
|
def onRadioButtonSelect(self, index, status):
|
|
"""单选按钮选择事件"""
|
|
if status:
|
|
self.updateStatus(f"选中单选按钮: {index + 1}")
|
|
print(f"选中单选按钮: {index + 1}")
|
|
|
|
def onOptionMenuSelect(self, arg):
|
|
"""选项菜单选择事件"""
|
|
self.updateStatus(f"选择了: {arg}")
|
|
print(f"选择了选项: {arg}")
|
|
|
|
def updateStatus(self, message):
|
|
"""更新状态显示"""
|
|
self.statusText.setText(f"状态: {message}")
|
|
|
|
def exitApp(self):
|
|
"""退出应用程序"""
|
|
print("正在退出程序...")
|
|
self.userExit()
|
|
|
|
if __name__ == "__main__":
|
|
try:
|
|
app = GUITestApp()
|
|
app.run()
|
|
except Exception as e:
|
|
print(f"程序运行出错: {e}")
|
|
sys.exit(1) |