Thread.join()不允许线程本身更新GUI

时间:2014-09-01 01:04:01

标签: python multithreading pygtk

我有问题:我调用thread.join(),我确定该线程正在通过stdout日志记录正确工作,但它无法更新GUI 即可。

示例非常简单:线程应该更新进度条5次:进度条在时间0开始完全清空,并在时间5完全填满。每次更新都会发生每秒,所以总共需要5秒钟。

在thread.join()之后会显示另一个窗口

但问题是,在thread.join()的那一刻,我只能看到stdout日志记录,但进度条没有被更新。我必须等待5秒,然后我才能看到一个完全填充的进度条,最后显示另一个窗口。

所以我无法在5秒钟内看到我的GUI,我的进度条的任何更新

以下是代码:

def Interrupt_Button_clicked(widget, args=()):

    t = threading.Thread(target=pulsing2, args=())
    t.setDaemon(True)
    t.start()
    t.join()
    builder.get_object('Azioni_Window').show()


def pulsing2():

    progressbar.set_inverted(True)
    fraction = 0.0
    while True:
        fraction += 0.2
        progressbar.set_fraction(fraction)
        print fraction # THIS WORKS CORRECTLY EVERY TIME, 5 TIMES IN TOTAL (1/0.2)
        time.sleep(1)
        if fraction == 1:
            break

progressbar = builder.get_object('Progressbar1')
builder.get_object('Ferma_trovarete_Button').connect('clicked', Interrompi_Button_clicked)
builder.get_object('Trovarete_Window').show()
Gtk.main()

1 个答案:

答案 0 :(得分:1)

您正在尝试从后台线程更新GUI,而GTK不支持。如果需要从后台线程更新GUI,请使用gobject.idle_add来安排在主线程中更新小部件。

def pulsing2(callback=None):

    progressbar.set_inverted(True)
    fraction = 0.0
    while True:
        fraction += 0.2
        gobject.idle_add(progressbar.set_fraction, fraction)
        print fraction # THIS WORKS CORRECTLY EVERY TIME, 5 TIMES IN TOTAL (1/0.2)
        time.sleep(1)
        if fraction == 1:
            break
    gobject.idle_add(builder.get_object('Azioni_Window').show)

您还需要从t.join()中删除对Interrupt_Button_clicked的调用,因为它会阻止函数调用中的主线程,这意味着gtk事件循环将无法运行,实际上更新了GUI小部件。

那就是说,我认为你可以重构这一点,根本不使用线程,而是使用gobject.timeout_add安排更新代码每秒运行一次:

def Interrupt_Button_clicked(widget, args=()):
    def cb():
        builder.get_object('Azioni_Window').show()
        print ("pulsing2 is done")

    pulsing2(callback=cb)

def pulsing2(fraction=0.0, callback=None):  
    progressbar.set_inverted(True)
    fraction += 0.2
    progressbar.set_fraction(fraction)
    print fraction # THIS WORKS CORRECTLY EVERY TIME, 5 TIMES IN TOTAL (1/0.2)
    if fraction != 1:
        gobject.add_timeout(1, pulsing2, fraction, callback)
    else:
        if callback:
            gobject.idle_add(callback)