PyGTK、线程与WebKit
在我的PyGTK应用程序中,当我点击按钮时,我需要:
- 获取一些HTML内容(这可能需要一些时间)
- 在新窗口中显示这些内容
在获取HTML内容的过程中,我希望保持界面可以响应用户操作,所以我决定在一个单独的线程中进行这个操作。我使用WebKit来渲染HTML。
问题是,当WebView在单独的线程中时,我得到的是一个空白页面。
这个方法是有效的:
import gtk
import webkit
webView = webkit.WebView()
webView.load_html_string('<h1>Hello Mars</h1>', 'file:///')
window = gtk.Window()
window.add(webView)
window.show_all()
gtk.mainloop()
但是这个方法不行,会产生一个空窗口:
import gtk
import webkit
import threading
def show_html():
webView = webkit.WebView()
webView.load_html_string('<h1>Hello Mars</h1>', 'file:///')
window = gtk.Window()
window.add(webView)
window.show_all()
thread = threading.Thread(target=show_html)
thread.setDaemon(True)
thread.start()
gtk.mainloop()
这是不是因为WebKit不是线程安全的?有没有什么解决办法呢?
2 个回答
0
我对webkit的内部工作原理不太了解,不过你可以试试用多个进程来解决这个问题。
3
根据我的经验,有时候在使用gtk时,更新小部件(也就是界面上的元素)在不同的线程中并不会像你预期的那样工作。
为了解决这个问题,你可以在线程中处理数据,然后使用 glib.idle_add
来安排在主线程中更新小部件,这样一旦数据处理完成,就可以更新界面了。
下面的代码是你例子的一个更新版本,对我来说是有效的(time.sleep
用来模拟在真实场景中获取html时的延迟):
import gtk, glib
import webkit
import threading
import time
# Use threads
gtk.gdk.threads_init()
class App(object):
def __init__(self):
window = gtk.Window()
webView = webkit.WebView()
window.add(webView)
window.show_all()
self.window = window
self.webView = webView
def run(self):
gtk.main()
def show_html(self):
# Get your html string
time.sleep(3)
html_str = '<h1>Hello Mars</h1>'
# Update widget in main thread
glib.idle_add(self.webView.load_html_string,
html_str, 'file:///')
app = App()
thread = threading.Thread(target=app.show_html)
thread.start()
app.run()
gtk.main()