滑块的标题不可见 (VPython)

Captions of slider not visible (VPython)

提问人:Chris Ze Third 提问时间:4/13/2023 更新时间:4/22/2023 访问量:51

问:

我用VPython创建了一个小小的3D模拟。有了它,滑块可以控制位置和颜色或对象。但是,我找不到一种方法来显示标题来指示滑块的内容。

我在定义滑块时添加了一个参数。我没有收到任何错误消息,因此我认为它的定义是正确的,但标题可能被隐藏或我在某处遗漏了某个步骤。wtitle

这是我的代码:

""" Import libraries """

import vpython as vp
    
""" Create Canvas """

canvas = vp.canvas(width=1080, height=720)
scene = vp.scene

""" Create objects """

# Define the planet
planet_radius = 5
# planet_texture = 'planet.jpg'  # You can replace this with your own custom picture
planet = vp.sphere(radius=planet_radius, texture=vp.textures.earth, shininess=0)

def atm_opacity(wavelength):
    return atm_density * (550 / wavelength)**4

# Define the atmosphere
atm_thickness = 3.0  # You can modify this using a slide cursor
atm_density = 0.5  # You can modify this using a slide cursor
atm_radius = planet.radius+atm_thickness
atm = vp.sphere(radius=atm_radius, opacity=0.25)
atm.opacity_function = atm_opacity

# Define the light source

def light_color(wavelength):
    r, g, b = 0, 0, 0
    if wavelength >= 400 and wavelength < 440:
        r = -(wavelength - 440) / (440 - 400)
        b = 1.0
    elif wavelength >= 440 and wavelength < 490:
        g = (wavelength - 440) / (490 - 440)
        b = 1.0
    elif wavelength >= 490 and wavelength < 510:
        g = 1.0
        b = -(wavelength - 510) / (510 - 490)
    elif wavelength >= 510 and wavelength < 580:
        r = (wavelength - 510) / (580 - 510)
        g = 1.0
    elif wavelength >= 580 and wavelength < 645:
        r = 1.0
        g = -(wavelength - 645) / (645 - 580)
    elif wavelength >= 645 and wavelength <= 700:
        r = 1.0
    return vp.vector(r, g, b)

light_type = 'red'  # You can modify this using a drop-down menu
# light_wavelength = 550  # You can modify this using a slide cursor
light_size = 2  # You can modify this using a slide cursor
light_intensity = 1.0  # You can modify this using a slide cursor
pos_drift = 50
light_xpos = atm_radius+pos_drift
light_ypos = atm_radius+pos_drift
light_zpos = atm_radius+pos_drift
light_pos = vp.vector(light_xpos, light_ypos, light_zpos)
wavelength = 400
light = vp.local_light(pos=light_pos, color= light_color(wavelength), radius=light_size)
light.color_function = light_color


# 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 = 'Click and drag on the light source to move it. Use the drop-down menu and slide cursors to adjust its properties.'

""" 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

# Bind the event handlers
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)

# Create the slider to rotate the light source around
def set_rotation_angle(slider):
    # light.rotate(angle=slider.value, axis=vp.vector(0, 1, 0), origin=planet.pos)
    
    # Calculate the rotation angle
    angle = vp.radians(slider.value)
    
    # Calculate the new position of the object
    x = atm_radius+pos_drift * vp.cos(angle)
    y = 0
    z = atm_radius+pos_drift * vp.sin(angle)
    
    # Set the position of the object
    light.pos = vp.vector(x, y, z)

# Create the slider
slider = vp.slider(wtitle='Rotate light source', min=0, max=360, step=1, value=0, bind=set_rotation_angle)

# Create slider to change light source wavelength
def WL_cursor(slider):
    val = slider.value
    new_wavelength = light_color(val)
    global light
    light.color = new_wavelength
    
slider = vp.slider(wtitle='Change light source color', min=400, max=700, length=250, bind=WL_cursor)

# Define the white light button
def white():
    global light
    light.color = vp.color.white

# Create the exit button
white_button = vp.button(bind=white, text="White light")

""" Run the simulation """

while True:
    vp.rate(30)
    
    # Update the atmosphere
    atm.radius = planet.radius+atm_thickness
    atm.opacity = 0.25*atm_density
    
    # Update the light source
    light.radius = light_size
    light.intensity = light_intensity
    light.pos = light.pos

    # Update the camera
    vp.scene.center = planet.pos
Python 3D 滑块 vpython

评论


答:

1赞 Chris Ze Third 4/14/2023 #1

出于某种原因,您需要将其添加到滑块中,而不是将滑块添加到中。所以像这样:scenecanvas

slider_angle = vp.slider(wtitle='Rotate light source', min=0, max=360, step=1, value=0, bind=set_rotation_angle, right=15)
canvas.append_to_caption('Slide the cursor to move the light source.')
canvas.append_to_caption('\n\n')
1赞 user1114907 4/22/2023 #2

VPython 会自动创建一个名为“scene”(或您中为“vp.scene”)的画布。然后说 scene = vp.scene,并设置此画布的各种属性,例如 scene.autoscale = False。但是,您还会创建第二个画布,名为 canvas: canvas = vp.canvas(...)。您的大多数程序都引用了名为 scene 的画布,但您将“mousedown”绑定到 canvas,这很令人困惑。最干净的方法是删除“画布”的创建并将鼠标向下绑定到场景。