【问题标题】:Pause Jupyter Notebook widgets, waiting for user input暂停 Jupyter Notebook 小部件,等待用户输入
【发布时间】:2019-08-10 05:00:19
【问题描述】:

我遇到了与 TheInterestedOne 提出的 here 相同的问题。

我需要为用户创建两个按钮,并建议用户点击循环中的两个按钮之一;以便循环的下一次迭代仅在用户选择之后发生。

我阅读了this source,但我无法让它适用于按钮。我不明白,在使用按钮的情况下,小部件属性如何变化。

from functools import wraps
def yield_for_change(widget, attribute):
    def f(iterator):
        @wraps(iterator)
        def inner():
            i = iterator()
            def next_i(change):
                try:
                    i.send(change.new)
                except StopIteration as e:
                    widget.unobserve(next_i, attribute)
            widget.observe(next_i, attribute) //**button.on_click(on_button_clicked) 
                                                                may be?**
            # start the generator
            next(i)
        return inner
    return f


from ipywidgets import Button
button=Button()


def on_button_clicked():
    print("Button clicked.")


@yield_for_change(button, 'value')
def f():
    for i in range(10):
        print('did work %s'%i)
        x = yield
        button.on_click(on_button_clicked)

【问题讨论】:

  • 嗨,欢迎来到 stackoverflow。如果您展示您尝试过的代码的具体示例以及失败的地方,您将更有可能从某人那里得到答案。见minimal reproducible example

标签: python button widget jupyter-notebook ipywidgets


【解决方案1】:

此版本使用awaitio 并针对按钮进行了修改。

from ipywidgets import Button
import asyncio

def wait_for_change(widget):
    future = asyncio.Future()
    def getvalue(change):
        future.set_result(change.description)
        widget.on_click(getvalue, remove=True) 
        # we need to free up the binding to getvalue to avoid an InvalidState error
        # buttons don't support unobserve
        # so use `remove=True` 
    widget.on_click(getvalue)
    return future

button = Button(description="wow")

list_to_tag = ["one", "two", "three", "four"]

async def f():
    for i in list_to_tag:
        print("going to tag {}".format(i))
        x = await wait_for_change(button)
        print("tagged {} with {}".format(i, x))
        print()

asyncio.create_task(f())
button

【讨论】:

  • 您能否添加多个按钮,以便我可以使用其中一个按钮标记列表中的项目?
【解决方案2】:

要拥有多个按钮,您可以将其他小部件添加到 @IanMulvany 先前的答案之一。

请参阅下面代码中的

from ipywidgets import Button, HBox #<----- Add HBox for displaying multiple buttons
import asyncio

def wait_for_change(widget1, widget2): #<------ Rename to widget1, and add widget2
    future = asyncio.Future()
    def getvalue(change):
        future.set_result(change.description)
        widget1.on_click(getvalue, remove=True) #<------ Rename to widget1
        widget2.on_click(getvalue, remove=True) #<------ New widget2
        # we need to free up the binding to getvalue to avoid an IvalidState error
        # buttons don't support unobserve
        # so use `remove=True` 
    widget1.on_click(getvalue) #<------ Rename to widget1
    widget2.on_click(getvalue) #<------ New widget2
    return future

button1=Button(description="wow") #<------ Rename to button1
button2=Button(description="wow2") #<------ New button2 and description

list_to_tag = ["one", "two", "three", "four"]

async def f():
    for i in list_to_tag:
        print('going to tag ', i)
        x = await wait_for_change(button1,button2) #<---- Pass both buttons into the function
        if x == "wow": #<--- use if statement to trigger different events for the two buttons
            print("tagged ", i, "with  %s"%x)
        else:
            print(i, "tagged with %s"%x)
        print("")
        print("")

asyncio.create_task(f())
HBox([button1,button2]) #<----Display both buttons in an HBox

【讨论】:

    【解决方案3】:

    这是适用于Button 的示例。主要变化在于装饰器,将observe 替换为on_click,这在某种程度上相当于观察按钮。

    from functools import wraps
    def yield_for_change(widget):
        def f(iterator):
            @wraps(iterator)
            def inner():
                i = iterator()
                def next_i(change):
                    try:
                        i.send(change)
                    except StopIteration as e:
                        widget.unobserve(next_i, attribute)
                widget.on_click(next_i)
                # start the generator
                next(i)
            return inner
        return f
    
    
    from ipywidgets import Button
    button=Button()
    
    def on_button_clicked():
        print("Button clicked.")
    
    
    @yield_for_change(button)
    def f():
        for i in range(10):
            print('did work %s'%i)
            x = yield
    
    f()
    
    button
    

    【讨论】:

    • 如果我想让按钮在每次迭代时都改变怎么办?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-24
    • 1970-01-01
    • 2017-06-17
    • 2016-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多