Не пытайтесь обновить или получить доступ к вашему графическому интерфейсу из потока. Вы просто напрашиваетесь на неприятности. Например, тот факт, что "get_text
" работает на всех в потоке, является почти случайностью. Возможно, вы сможете положиться на него в GTK - хотя я даже не уверен в этом - но вы не сможете сделать это в других инструментах GUI.
Если у вас есть вещи, которые действительно нужно выполнять в потоках, вы должны получить необходимые данные из графического интерфейса пользователя до запуска потока, а затем обновить графический интерфейс из потока, используя idle_add
это:
import time
import gtk
import gobject
from threading import Thread
w = gtk.Window()
h = gtk.HBox()
v = gtk.VBox()
addend1 = gtk.Entry()
h.add(addend1)
h.add(gtk.Label(" + "))
addend2 = gtk.Entry()
h.add(addend2)
h.add(gtk.Label(" = "))
summation = gtk.Entry()
summation.set_text("?")
summation.set_editable(False)
h.add(summation)
v.add(h)
progress = gtk.ProgressBar()
v.add(progress)
b = gtk.Button("Do It")
v.add(b)
w.add(v)
status = gtk.Statusbar()
v.add(status)
w.show_all()
def hardWork(a1, a2):
messages = ["Doing the hard work to add %s to %s..." % (a1, a2),
"Oof, I'm working so hard...",
"Almost done..."]
for index, message in enumerate(messages):
fraction = index / float(len(messages))
gobject.idle_add(progress.set_fraction, fraction)
gobject.idle_add(status.push, 4321, message)
time.sleep(1)
result = a1 + a2
gobject.idle_add(summation.set_text, str(result))
gobject.idle_add(status.push, 4321, "Done!")
gobject.idle_add(progress.set_fraction, 1.0)
def addthem(*ignored):
a1 = int(addend1.get_text())
a2 = int(addend2.get_text())
Thread(target=lambda : hardWork(a1, a2)).start()
b.connect("clicked", addthem)
gtk.gdk.threads_init()
gtk.main()
Если вам действительно необходимо прочитать данные из графического интерфейса в середине потока (это действительно плохая идея, не делайте этого - вы можете попасть в действительно удивительные тупики, особенно когда программа закрывается ) в Twisted есть утилита blockingCallFromThread , которая сделает за вас тяжелую работу. Вы можете использовать это так:
from twisted.internet.gtk2reactor import install
install()
from twisted.internet import reactor
from twisted.internet.threads import blockingCallFromThread
from threading import Thread
import gtk
w = gtk.Window()
v = gtk.VBox()
e = gtk.Entry()
b = gtk.Button("Get Text")
v.add(e)
v.add(b)
w.add(v)
def inThread():
print 'Getting value'
textValue = blockingCallFromThread(reactor, e.get_text)
print 'Got it!', repr(textValue)
def kickOffThread(*ignored):
Thread(target=inThread).start()
b.connect("clicked", kickOffThread)
w.show_all()
reactor.run()
Если вы хотите увидеть, как работает магия, вы всегда можете прочитать источник .