如何在一个ipywidget的回调中更新另一个ipywidget?

huangapple go评论76阅读模式
英文:

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)

如何在一个ipywidget的回调中更新另一个ipywidget?

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(&#39;Initial text&#39;, display_id = True)

        def on_button_click(b, label):
            label.update(&#39;New number {}&#39;.format(random.random()))

        button = widgets.Button(description=&quot;New number&quot;)
        display(button)           
        button.on_click(functools.partial(on_button_click, label=label))


button = widgets.Button(description=&quot;Button&quot;)
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(&#39;Initial text&#39;)
out = widgets.HBox([text])

def foo(b):
  text.value = &#39;New number {}&#39;.format(random.random())
  # alternatively: out.children = [widgets.Text(&#39;New number {}&#39;.format(random.random()))]

button = widgets.Button(description=&quot;Button&quot;)
button.on_click(foo)
display(button)
display(out)

huangapple
  • 本文由 发表于 2020年1月3日 18:55:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/59577302.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定