python 散景:当 adding/changing 儿童在密码保护的仪表板中时,交互丢失。

python bokeh: Interaction lost when adding/changing children in a password secured dashboard.

我想向散景仪表板添加密码功能(基于所示示例的修改和扩展代码 here。背后的逻辑是我创建了一个带有 "passblock" 项目的仪表板其中可以输入密码,第二个块是空的。如果密码正确,"passblock" 项将被删除,空占位符 bloxk 将由交互式仪表板块填充。 在此示例中,交互式仪表板是滑块,如果您更改它,则通过回调函数打印值。 如果我直接在仪表板部分包含一个范围滑块(请参阅注释部分),虽然回调工作正常,但如果密码和用户输入正确,它就不再工作了。 即使我之前添加 range_slider 并且仅在 verify_pwd 部分中将其替换为新的,它也不起作用。任何想法表示赞赏。

from bokeh.models.widgets import PasswordInput,Button, TextInput,PreText,RangeSlider
from bokeh.layouts import column, row

PASSWD = "1" #password
USER   = "1" #username
max_count_tries = 5 #max allowed tries before dashboard is killed
count_tries = 0  # counter for max tries

def verify_pwd():
    """ verifies if user and pwd are entered correctly. If so the password block is set to zero and the
    dashboard block which was zero before is replaced by the slider"""
    global count_tries
    global range_slider
    if (pwd.value==PASSWD) & (user.value == USER): #pwe and user entered correctly
        print('logged in')
        range_slider = RangeSlider(start=0., end=10., value=(2.,3.), step=.1, title="secret slider")
        layout.children[0] = row([])
        layout.children[1] = row([range_slider])
    else: #pwd or user are wrong
        if (pwd.value!=PASSWD) & (user.value == USER):
            mytext.text = ''.join(['wrong password!\n',str(max_count_tries-count_tries), ' tries left'])
        elif (pwd.value==PASSWD) & (user.value != USER):
            mytext.text = ''.join(['wrong user!\n',str(max_count_tries-count_tries), ' tries left'])
        else:
            mytext.text = ''.join(['wrong user and wrong password!\n',str(max_count_tries-count_tries), ' tries left'])
        count_tries += 1
        if count_tries>max_count_tries:
           layout.children[0] = row([])

def callback(attrname, old, new):
    # Get the current slider values and print the value in the console
    global range_slider
    lower = range_slider.value[0]    
    upper = range_slider.value[1]   
    print(lower,upper)

mytext = PreText() #placeholder for error message
user = TextInput(title="UserName:") # unser name entry field
pwd  = PasswordInput(title="Password:") #password entry field
btn  = Button(label="login") # button to log in 
btn.on_click(verify_pwd) # if button was clicked compare pwd and user with entries
#pwd.callback(verify_pwd)

passblock = row([user, pwd, btn, mytext]) # create a block to the dashboard where the pwd and user can be entered

range_slider = RangeSlider(start=0., end=10., value=(0.,0.), step=.1, title="dummy") # create a dummy slider which is not used
range_slider.on_change('value', callback) # callback for slider if values change

layout = column(passblock,row([])) # create a layout with the password block and an empty block which is filled as soon as the pwd and user are ok
#layout = column(passblock,range_slider)

# create bokeh document and deploy it
from bokeh.io import curdoc
curdoc().add_root(layout)

玩了一段时间后,我找到了解决办法。在上面的代码中,我忘记在 verify_pwd 子例程中添加 "on_change" 行。 添加

range_slider.on_change('value', callback) 

在行中添加新滑块后:

range_slider = RangeSlider(start=0., end=10., value=(2.,3.), step=.1, title="secret slider")

解决了问题

或者它也适用于问题中描述的版本

layout.children[0] = row([])
layout.children[1] = row([range_slider])

替换为

layout.children[0] = row([range_slider])