动态更新 Holoviz 面板布局
Dynamically updating a Holoviz Panel layout
在不讨论动机细节的情况下,我想使用面板执行以下步骤序列:
- 显示一个 panel.widgets.FileInput 元素。
- 选择文件后,显示一个 panel.widgets.MultiSelect 元素,其中包含文件中的项目,其中前几个被选中。 MultiSelect 元素显示在 FileInput 元素下方。
- 根据所选内容(最初以及通过用户与 panel.widgets.MultiSelect 元素的交互),在 FileInput 元素右侧的列中显示一些项目。
第 1 步和第 2 步工作正常,但我无法让第 3 步发生。这是说明问题的最小示例 运行:
import panel as pn
pn.extension()
# Create and organize basic elements to show where things go
file_input = pn.widgets.FileInput()
item_selector = pn.widgets.MultiSelect()
controls = pn.Column(file_input, "layout[0][1]")
layout = pn.Row(controls, pn.Column("layout[1][0]"))
print(layout)
# Set up selector object
@pn.depends(file_contents=file_input, watch=True)
def _item_selector(file_contents):
# Dummy items for illustration purpose
items = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
item_selector = pn.widgets.MultiSelect(
name="Choose items",
options=items,
size=12,
width=120,
value=items[:2],
)
layout[0][1] = item_selector
# Define interactivity based on selector object
@pn.depends(selected_items=item_selector, watch=True)
def _col(selected_items):
col = pn.Column()
for item in selected_items:
col.append(item)
layout[1] = col
layout
任何有助于消除我的误解的指示都将不胜感激。
我知道我错在哪里了。在函数_item_selector()
中我将layout[0][1]
设置为一个新的MultiSelect对象,函数_col()
受第6行设置的原始MultiSelect对象的影响。下面的代码解决了这个问题
import panel as pn
pn.extension()
# Create and organize basic elements to show where things go
file_input = pn.widgets.FileInput()
item_selector = pn.widgets.MultiSelect()
controls = pn.Column(file_input, "")
layout = pn.Row(controls, pn.Column(""))
# Set up selector object
@pn.depends(file_contents=file_input, watch=True)
def _item_selector(file_contents):
# Dummy file contents
items = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
item_selector.options = items
item_selector.value = ['a', 'c']
item_selector.size = 12
item_selector.width = 120
layout[0][1] = item_selector
# Define interactivity based on selector object
@pn.depends(selected_items=item_selector, watch=True)
def _col(selected_items):
col = pn.Column()
for item in selected_items:
col.append(item)
layout[1] = col
layout
我确信这不是解决我要解决的问题的最优雅方法,我会对任何反馈感兴趣。特别是,作为Panel的新手,我不知道是否有必要在第5-8行预先设置布局,或者是否也可以动态完成。
在不讨论动机细节的情况下,我想使用面板执行以下步骤序列:
- 显示一个 panel.widgets.FileInput 元素。
- 选择文件后,显示一个 panel.widgets.MultiSelect 元素,其中包含文件中的项目,其中前几个被选中。 MultiSelect 元素显示在 FileInput 元素下方。
- 根据所选内容(最初以及通过用户与 panel.widgets.MultiSelect 元素的交互),在 FileInput 元素右侧的列中显示一些项目。
第 1 步和第 2 步工作正常,但我无法让第 3 步发生。这是说明问题的最小示例 运行:
import panel as pn
pn.extension()
# Create and organize basic elements to show where things go
file_input = pn.widgets.FileInput()
item_selector = pn.widgets.MultiSelect()
controls = pn.Column(file_input, "layout[0][1]")
layout = pn.Row(controls, pn.Column("layout[1][0]"))
print(layout)
# Set up selector object
@pn.depends(file_contents=file_input, watch=True)
def _item_selector(file_contents):
# Dummy items for illustration purpose
items = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
item_selector = pn.widgets.MultiSelect(
name="Choose items",
options=items,
size=12,
width=120,
value=items[:2],
)
layout[0][1] = item_selector
# Define interactivity based on selector object
@pn.depends(selected_items=item_selector, watch=True)
def _col(selected_items):
col = pn.Column()
for item in selected_items:
col.append(item)
layout[1] = col
layout
任何有助于消除我的误解的指示都将不胜感激。
我知道我错在哪里了。在函数_item_selector()
中我将layout[0][1]
设置为一个新的MultiSelect对象,函数_col()
受第6行设置的原始MultiSelect对象的影响。下面的代码解决了这个问题
import panel as pn
pn.extension()
# Create and organize basic elements to show where things go
file_input = pn.widgets.FileInput()
item_selector = pn.widgets.MultiSelect()
controls = pn.Column(file_input, "")
layout = pn.Row(controls, pn.Column(""))
# Set up selector object
@pn.depends(file_contents=file_input, watch=True)
def _item_selector(file_contents):
# Dummy file contents
items = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
item_selector.options = items
item_selector.value = ['a', 'c']
item_selector.size = 12
item_selector.width = 120
layout[0][1] = item_selector
# Define interactivity based on selector object
@pn.depends(selected_items=item_selector, watch=True)
def _col(selected_items):
col = pn.Column()
for item in selected_items:
col.append(item)
layout[1] = col
layout
我确信这不是解决我要解决的问题的最优雅方法,我会对任何反馈感兴趣。特别是,作为Panel的新手,我不知道是否有必要在第5-8行预先设置布局,或者是否也可以动态完成。