0

私はこのコードを持っています:

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

なぜこれが起こっているのか、それを回避/修正する方法は?

4

2 に答える 2

0

以下は、説明のみを目的とした単純なダウンローダーの実例です。GUIの応答性を高め、長時間実行またはブロック操作を実行しているときにフリーズしないようにする場合は、マルチスレッドを使用する必要があります。このスタックオーバーフローの質問とこの優れた記事「PyGTKでのスレッドの使用」に基づいて、この例をまとめました。Ubuntuisoのデフォルトの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()
于 2012-10-02T20:19:14.563 に答える
0

メインループが実行されるまで、Gtk は何も更新しません。つまり、最初にすべての変更を行い、すべての変更が完了してから更新するだけです。これは、すべてのコールバックがアトミックであること (無視できる時間で終了すること) を意図しているためです。インターフェイスがフリーズすることを意味するため、コールバックでブロッキング呼び出しを使用しないでください。

ここで考えられる解決策は 2 つあります。最善の方法は、応答の準備が整ったときに新しいコールバックを登録し、メイン ループに戻ることです。ただし、これは簡単ではないかもしれません。汚い回避策は、ブロッキング呼び出しを行う前に、メイン ループが保留中のイベントを強制的に処理することです。次に、ラベルを更新します。これを行うことができます

while gtk.events_pending ():
    gtk.main_iteration (False)

しかし、私が書いたように、コールバックからブロッキング関数を呼び出さない方がはるかにクリーンです。

于 2012-10-02T19:55:00.410 に答える