我有一个应用程序可以在后台创建一些东西。为了通知用户,它会更新一些小部件及其进度。这很有效。
但有些事情在这个后台操作中有错误或其他东西,所以它必须显示一个对话框。虽然我使用Threading-Lock处理所有内容,但这会冻结我的整个应用程序。完全是我的问题的代码示例如下:
import threading, time
from gi.repository import Gtk, Gdk
def background(label, parent):
for t in range(5):
label.set_text(str(t))
time.sleep(1)
Gdk.threads_enter()
dlg = Gtk.MessageDialog(
type=Gtk.MessageType.INFO,
buttons=Gtk.ButtonsType.OK,
message_format="Time is gone.",
title="Info")
dlg.run()
dlg.destroy()
Gdk.threads_leave()
def main():
window = Gtk.Window()
window.connect("delete-event", Gtk.main_quit)
label = Gtk.Label()
window.add(label)
window.show_all()
thread = threading.Thread(target=background, args=(label, window))
Gdk.threads_init()
Gdk.threads_enter()
thread.start()
Gtk.main()
Gdk.threads_leave()
if __name__=="__main__":
main()
答案 0 :(得分:3)
在gtk3中,所有gtk函数(如添加/删除/更改小部件)必须由gtk线程(运行Gtk.main()
的线程)执行。
固定代码:
import threading, time
from gi.repository import Gtk, Gdk, GLib # need GLib for GLib.PRIORITY_DEFAULT
# a short utility function that I like to use.
# makes the Gtk thread execute the given callback.
def add_mainloop_task(callback, *args):
def cb(args):
args[0](*args[1:])
return False
args= [callback]+list(args)
Gdk.threads_add_idle(GLib.PRIORITY_DEFAULT, cb, args)
def background(label, parent):
for t in range(5):
#~ label.set_text(str(t)) # let the gtk thread do this.
add_mainloop_task(label.set_text, str(t))
time.sleep(1)
#~ Gdk.threads_enter() # don't need this.
dlg = Gtk.MessageDialog(
type=Gtk.MessageType.INFO,
buttons=Gtk.ButtonsType.OK,
message_format="Time is gone.",
title="Info")
# put these two functions calls inside a little function, and let the gtk thread execute it.
def run_dialog(dlg):
dlg.run()
dlg.destroy()
add_mainloop_task(run_dialog, dlg)
#~ Gdk.threads_leave() # don't need this.
def main():
window = Gtk.Window()
window.connect("delete-event", Gtk.main_quit)
label = Gtk.Label()
window.add(label)
window.show_all()
thread = threading.Thread(target=background, args=(label, window))
Gdk.threads_init()
#~ Gdk.threads_enter() # don't need this.
thread.start()
Gtk.main()
#~ Gdk.threads_leave() # don't need this.
if __name__=="__main__":
main()