0

I have this code :

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()

The self.lbl_status doesn't change till the request is finished, so it displays nothing due to the last set_text function.

Why is this happening, and how to avoid/fix that?

Bruno von Paris
  • 882
  • 1
  • 7
  • 26
Rami Dabain
  • 4,709
  • 12
  • 62
  • 106
  • what gui library are you using? – Marwan Alsabbagh Oct 02 '12 at 18:54
  • GTK i think . am on quickly ubuntu 12.04 – Rami Dabain Oct 02 '12 at 18:56
  • what are the import statements you have at the top of your script. just to be sure of the GUI library you are using – Marwan Alsabbagh Oct 02 '12 at 18:58
  • here are all : import gettext import httplib, urllib from gettext import gettext as _ gettext.textdomain('noc-client') from gi.repository import Gtk # pylint: disable=E0611 import logging logger = logging.getLogger('noc_client') from noc_client_lib import Window from noc_client.AboutNocClientDialog import AboutNocClientDialog from noc_client.PreferencesNocClientDialog import PreferencesNocClientDialog – Rami Dabain Oct 02 '12 at 19:01
  • is it possible that it finishes the whole process so fast you just can't see the updates? – andrean Oct 02 '12 at 19:22

2 Answers2

0

Gtk doesn't update anything until the main loop runs. That means it first does all its changes and only updates after they're all done. This is because it intends all callbacks to be atomic (finish in a negligible time). A callback should never use a blocking call, because it means the interface will freeze.

There are two possible solutions here. The best is to register a new callback when a response is ready, and return to the main loop. However, this may not be easy. A dirty workaround is to force the main loop to handle pending events before making the blocking call. It will then update the label. You can do this with

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

But as I wrote, not calling any blocking functions from the callback is much cleaner.

shevek
  • 31
  • 1
0

Below is a working example of a simple downloader for illustration purposes only. You need to use multi-threading if you want your GUI to be responsive and not freeze while you do some long running or blocking operation. I put this example together based on this stack overflow question and this excellent article Using threads in PyGTK. The default url an Ubuntu iso will take a while to download and should provide a good demonstration . You can enter any url you want when prompted it will download and save the file in the current directory.

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()
Community
  • 1
  • 1
Marwan Alsabbagh
  • 25,364
  • 9
  • 55
  • 65