VPython中通过菜单修改局部光源颜色失效问题求助
VPython光源颜色下拉菜单修改失效问题修复方案
问题根源
你的代码里主循环每帧都会根据light_type变量重置光源颜色,但菜单回调函数M只修改了light.color,没有同步更新light_type;而且初始light_type设为'sun',主循环每秒执行30次,每次都把颜色强制设为白色,导致你通过菜单设置的颜色瞬间被覆盖,出现闪一下或无变化的现象。
修复方案
两种简单修复方式,选其一即可:
方案一:同步更新light_type变量
在菜单回调函数里,修改颜色的同时更新全局light_type,让主循环的颜色逻辑和菜单选择保持一致:
def M(m): global light, light_type # 新增light_type全局声明 val = m.selected if val == "sun": light.color = vp.color.white light_type = 'sun' # 同步更新变量 elif val == "red": light.color = vp.color.red light_type = 'red_dwarf' # 对应主循环里的类型 elif val == "yellow": light.color = vp.color.yellow light_type = 'yellow' # 可新增该类型到主循环,或直接移除主循环颜色逻辑 elif val == "blue": light.color = vp.color.blue light_type = 'blue'
方案二:移除主循环的颜色重置逻辑
既然已经通过菜单直接控制光源颜色,主循环里的颜色判断完全多余,直接删除这部分代码:
# 删掉主循环里这段代码 # if light_type == 'sun': # light.color = vp.color.white # elif light_type == 'red_dwarf': # light.color = vp.color.red # elif light_type == 'white_dwarf': # light.color = vp.color.white
修改后的完整代码(以方案二为例,更简洁)
""" Import libraries """ import vpython as vp import numpy as np import sys """ Create Canvas """ canvas = vp.canvas(width=1080, height=720) scene = vp.scene """ Create objects """ # Define the planet planet_radius = 5 planet_texture = 'planet.jpg' # 可替换为自定义图片 planet = vp.sphere(radius=planet_radius, texture=vp.textures.earth, shininess=0) # Define the atmosphere atm_thickness = 3.0 # 可用滑块修改 atm_density = 0.5 # 可用滑块修改 atm_radius = planet.radius+atm_thickness atm = vp.sphere(radius=atm_radius, opacity=0.25) # Define the light source light_type = 'sun' # 该变量可保留或删除,不再用于控制颜色 light_wavelength = 550 # 可用滑块修改 light_size = 2 # 可用滑块修改 light_intensity = 1.0 # 可用滑块修改 pos_drift = 50 light_pos = vp.vector(atm_radius+pos_drift, atm_radius+pos_drift, atm_radius+pos_drift) light = vp.local_light(pos=light_pos, color=vp.color.red, radius=light_size) # Define the camera scene.autoscale = False scene.range = 10 scene.forward = vp.vector(0, 0, -1) scene.up = vp.vector(0, 1, 0) scene.caption = '点击拖拽光源移动,用下拉菜单和滑块调整属性。' """ Define the event handlers """ def on_light_down(evt): global light_dragging, light_drag_pos light_dragging = True light_drag_pos = evt.pos def on_light_move(evt): global light_dragging, light_drag_pos if light_dragging: light.pos += evt.pos - light_drag_pos light_drag_pos = evt.pos def on_light_up(evt): global light_dragging light_dragging = False # 绑定事件处理器 vp.scene.bind('mousedown', on_light_down) vp.scene.bind('mousemove', on_light_move) vp.scene.bind('mouseup', on_light_up) def on_mouse_down(event): global dragging, last_mouse_pos obj = scene.mouse.pick if obj == light: dragging = True last_mouse_pos = scene.mouse.pos canvas.bind('mousedown', on_mouse_down) # 控制光源X位置的滑块 def set_x_position(slider): light.pos.x = slider.value slider = vp.slider(min=-25, max=25, length=250, bind=set_x_position) # 修改光源颜色的下拉菜单 def M(m): global light val = m.selected if val == "sun": light.color = vp.color.white elif val == "red": light.color = vp.color.red elif val == "yellow": light.color = vp.color.yellow elif val == "blue": light.color = vp.color.blue menu = vp.menu(choices=['sun', 'red', 'yellow', 'blue'], index=0, bind=M) # 退出函数 def exit_simulation(): canvas.delete() # sys.exit() # 退出按钮 exit_button = vp.button(bind=exit_simulation, text="退出模拟") """ 运行模拟 """ while True: vp.rate(30) # 更新大气 atm.radius = planet.radius+atm_thickness atm.opacity = 0.25*atm_density # 更新光源 light.radius = light_size light.intensity = light_intensity # 更新相机 vp.scene.center = planet.pos # 更新行星纹理 planet.texture = planet_texture
说明
方案二更简洁直接,菜单直接负责颜色设置,主循环无需重复干预。如果需要保留light_type变量用于其他逻辑,就用方案一同步更新变量值,避免主循环和菜单的逻辑冲突。
内容的提问来源于stack exchange,提问作者Antonio
相关产品推荐
相关产品推荐

