我有这段代码:
def on_btn_login_clicked(self, widget):
email = self.log_email.get_text()
passw = self.log_pass.get_text()
self.lbl_status.set_text("Connecting ...")
params = urllib.urlencode({'@log_email': email, '@log_pass': passw, '@action': 'login', '@module': 'user'})
headers = {"Content-type": "application/x-www-form-urlencoded","Accept": "text/plain"}
conn = httplib.HTTPConnection("website.com")
self.lbl_status.set_text("Logging in ...")
conn.request("POST", "/ajax.php", params, headers)
response = conn.getresponse()
print response.status
self.lbl_status.set_text("")
data = response.read()
print data
conn.close()
self.lbl_status
在请求完成之前不会更改,因此,由于上一个set_text
功能,它不会显示任何内容。
为什么会发生这种情况,以及如何避免/解决这个问题?
答案 0 :(得分:0)
在主循环运行之前,Gtk不会更新任何内容。这意味着它首先完成所有更改,并且只有在完成后才进行更新。这是因为它打算所有回调都是原子的(在一个可以忽略的时间内完成)。回调永远不应该使用阻塞调用,因为这意味着接口将冻结。
这里有两种可能的解决方案。最好的方法是在响应准备就绪时注册一个新的回调,然后返回主循环。但是,这可能并不容易。一个肮脏的解决方法是在进行阻塞调用之前强制主循环处理挂起事件。然后它会更新标签。您可以使用
执行此操作while gtk.events_pending ():
gtk.main_iteration (False)
但正如我所写的那样,不回调回调中的任何阻塞函数就更清晰了。
答案 1 :(得分:0)
下面是一个简单下载器的工作示例,仅用于说明目的。如果您希望GUI执行响应并且在执行长时间运行或阻塞操作时不冻结,则需要使用多线程。我根据this stack overflow question和这篇优秀的文章Using threads in PyGTK将这个例子放在一起。 Ubuntu iso的默认URL需要一段时间才能下载,应该提供一个很好的演示。您可以在提示下载时输入您想要的任何URL,并将文件保存在当前目录中。
from threading import Thread
import time
import gtk, gobject, urllib
URL = 'http://releases.ubuntu.com//precise/ubuntu-12.04.1-desktop-i386.iso'
def download(url):
filename = url.split('/')[-1]
out = open(filename, 'wb')
gobject.idle_add(label.set_text, "connecting...")
f = urllib.urlopen(url)
buffer = f.read(1024)
counter = 0
while buffer:
counter += len(buffer)
out.write(buffer)
msg = "downloaded {0:,} bytes".format(counter)
gobject.idle_add(label.set_text, msg)
buffer = f.read(1024)
out.close()
gobject.idle_add(label.set_text, "download complete")
def clicked(button):
url = entry.get_text()
Thread(target=download, args=(url,)).start()
gtk.gdk.threads_init()
win = gtk.Window()
win.set_default_size(400, 100)
entry = gtk.Entry()
entry.set_text(URL)
label = gtk.Label("Press the button")
button = gtk.Button(label="Download")
button.connect('clicked', clicked)
box = gtk.VBox()
box.pack_start(entry)
box.pack_start(label)
box.pack_start(button)
win.add(box)
win.show_all()
gtk.main()