英文:
How to update a ipywidget called from the callback of an ipywidget?
问题
我有困难理解在IPython display
上的update
功能。
似乎要更新小部件,小部件需要在顶层进行实例化,而不能从ipywidget的回调中进行实例化。
以下是一个由ipywidget Button
调用的IPython display
的非工作示例:
import functools
import ipywidgets as widgets
from IPython.display import display
import random
def foo(b):
label = display('Initial text', display_id=True)
def on_button_click(b, label):
label.update('New number {}'.format(random.random()))
button = widgets.Button(description="New number")
display(button)
button.on_click(functools.partial(on_button_click, label=label))
button = widgets.Button(description="Button")
button.on_click(foo)
display(button)
在这个示例中,单击Button
按钮会显示一个文本label
和一个新的按钮New number
。然而,单击New number
并不会更新文本label
。
直接调用foo(0)
可以正常工作。当单击New number
按钮时,文本label
会更新。
这个代码示例有什么问题吗?为什么无法在从另一个小部件的回调中实例化时更新ipywidget?
英文:
I am having troubles understanding the functioning of update
on an IPython display
.
It seems that to be updated the widget needs to be instantiated at the top level and cannot be instantiated from the callback of an ipywidget.
Here is a non-working exampled of an IPython display
called by a ipywidget Button
:
import functools
import ipywidgets as widgets
from IPython.display import display
import random
def foo(b):
label = display('Initial text', display_id = True)
def on_button_click(b, label):
label.update('New number {}'.format(random.random()))
button = widgets.Button(description="New number")
display(button)
button.on_click(functools.partial(on_button_click, label=label))
button = widgets.Button(description="Button")
button.on_click(foo)
display(button)
In this example clicking on <kbd>Button</kbd> displays a text label
and a new button (<kbd>New number</kbd>).
However, clicking on <kbd>New number</kbd> does not update the text label
.
Calling foo(0)
directly works correctly. When the <kbd>New number</kbd> button is clicked, the text label
is updated.
Is something wrong with the code example? Why can't an ipywidget be updated if it is instantiated from the callback of another widget?
答案1
得分: 3
I have seen this issue before and it can be due with where the output is routed when using display
. I can get the desired behavior by wrapping your function with a context manager Output widget.
For anything more complex I would consider building a class deriving from HBox, containing an Output widget and various buttons.
import functools
import ipywidgets as widgets
from IPython.display import display
import random
out = widgets.Output()
def foo(b):
with out:
label = display('Initial text', display_id=True)
def on_button_click(b, label):
label.update('New number {}'.format(random.random()))
button = widgets.Button(description="New number")
display(button)
button.on_click(functools.partial(on_button_click, label=label))
button = widgets.Button(description="Button")
button.on_click(foo)
display(button)
display(out)
Please note that I have translated the code comments and strings but left the code itself unchanged.
英文:
I have seen this issue before and it can be due with where the output is routed when using display
. I can get the desired behaviour by wrapping your function with a context manager Output widget.
For anything more complex I would consider building a class deriving from HBox, containing an Output widget and various buttons.
import functools
import ipywidgets as widgets
from IPython.display import display
import random
out = widgets.Output()
def foo(b):
with out:
label = display('Initial text', display_id = True)
def on_button_click(b, label):
label.update('New number {}'.format(random.random()))
button = widgets.Button(description="New number")
display(button)
button.on_click(functools.partial(on_button_click, label=label))
button = widgets.Button(description="Button")
button.on_click(foo)
display(button)
display(out)
答案2
得分: 0
我认为您想要实现的是这样的:
import ipywidgets as widgets
from IPython.display import display
import random
text = widgets.Text('初始文本')
out = widgets.HBox([text])
def foo(b):
text.value = '新数字 {}'.format(random.random())
# 或者:out.children = [widgets.Text('新数字 {}'.format(random.random()))]
button = widgets.Button(description="按钮")
button.on_click(foo)
display(button)
display(out)
英文:
I think what you mean to achieve is this:
import ipywidgets as widgets
from IPython.display import display
import random
text = widgets.Text('Initial text')
out = widgets.HBox([text])
def foo(b):
text.value = 'New number {}'.format(random.random())
# alternatively: out.children = [widgets.Text('New number {}'.format(random.random()))]
button = widgets.Button(description="Button")
button.on_click(foo)
display(button)
display(out)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论