ipywidgets按钮:如何在正在运行的脚本中设置全局变量?

时间:2018-02-06 14:22:37

标签: python user-interface jupyter-notebook jupyter python-multithreading

我想使用ipywidgets按钮使我的脚本具有交互性。但我认为我缺少的GUI和线程有一些非常基础:按钮触发的功能似乎只在主脚本完成时调用!

我想实现这个GUI的方式是我的主循环执行一些计算并检查GUI在每次迭代时设置的参数。

让我们看一下这个例子,我们有一个开关按钮,然后应该改变主循环是执行一个还是另一个计算:

不工作示例

from ipywidgets import widgets
import threading, time

SWITCH = False
def onclick_switch(b):
    global SWITCH
    SWITCH = not SWITCH # toggle
    print('Button clicked! Switch: %s'%(SWITCH))

# set up GUI
button = widgets.Button( description='Switch')
button.on_click( onclick_switch )
display(button)

while True:
    if SWITCH:
        res = 2*2 # do sophisticated calculations / plots etc
        print('result: %s'%(res))
    else:
        res = 3*3 # do sophisticated calculations / plots etc
        print('result: %s'%(res))
    time.sleep(1)

按预期显示“切换”按钮,每秒打印第二次计算结果(“结果:9”)。但是,开关没有效果。只有在中断内核后才会评估按钮点击次数!

所以我想到如何将main函数放在一个单独的线程中,以免它干扰按钮?

近乎有效的例子

SWITCH = False
def onclick_switch(b):
    global SWITCH
    SWITCH = not SWITCH # toggle
    print('Button clicked! Switch: %s'%(SWITCH))

# set up GUI
button = widgets.Button( description='Switch')
button.on_click( onclick_switch )
display(button)

def mainloop(): # loop is now a function
    while True:
        if SWITCH:
            res = 2*2 # do sophisticated calculations / plots etc
            print('result: %s'%(res))
        else:
            res = 3*3 # do sophisticated calculations / plots etc
            print('result: %s'%(res))
        time.sleep(1)

mainthread = threading.Thread( target = mainloop ) # let's use threading
mainthread.start()

这更接近我想要的东西:但它只执行一次(打印“结果:9”一次),并且只在第一次按下按钮后继续。

我无法理解这种行为。但我确实理解这对于GUI来说是一般性的,因为如果我使用mpl_connect(也许还有qt / tkinter?)它也是一样的。

在我发现的ipywidgets示例中,没有主循环,每当用户更改任何内容时,总是只有一次执行绘图函数。这不是我需要的,我需要一个主循环!

那么一般如何做呢?按钮如何在内部工作,以便在主循环运行时无法执行?多线程/ GUI在哪里出错?

我正在使用ipywidgets 7.1.1和jupyter 5.4.0 with python 2.7

0 个答案:

没有答案