Display a label while pressing the button in my GUI

Peter Otten __peter__ at web.de
Mon Jan 30 08:26:16 EST 2017


Meeran Rizvi wrote:

> On Monday, January 30, 2017 at 12:02:40 PM UTC+5:30, Meeran Rizvi wrote:
>> Hello Guys,
>> Here i am creating a GUI which will act as a search engine that will find
>> the results from the browser and save the results as a xls file. When i
>> typed something in my search box and click the (GO)button.It should
>> display search in progress.when the file is saved it should display done.
>> How to do that? My button gets hung for a seconds.We should give any
>> timeout for that?
>> 
>> Here is my script
>> <python>
>> from Tkinter import *
>> import mechanize
>> def clear_search(event):
>>     search.delete(0,END)
>> obj = Tk()
>> Label = Label(obj,text="Top Findings:",font="-weight bold")
>> search = Entry(obj,width=100)
>> search.insert(0, "Enter the value to search")
>> search.bind("<Button-1>", clear_search)
>> def fun():
>>     new = search.get()
>>     url = "http://duckduckgo.com/html"
>>     br = mechanize.Browser()
>>     br.set_handle_robots(False)
>>     br.open(url)
>>     br.select_form(name="x")
>>     br["q"] = str(new)
>>     res = br.submit()
>>     content = res.read()
>>     with open("result1.xls", "w") as f:
>>         f.write(content)
>> fun()
>> Go = Button(obj,text="GO",width=5,command=fun)
>> Label.pack()
>> search.pack()
>> Go.pack()
>> mainloop()
>> </python>
> 
> Hi Peter,
> can u explain about these functions
> def start_search():

This creates a new thread; target and args specify that in that thread
fun will be invoked with the current contents of the search Entry.

>     thread = threading.Thread(
>         target=fun,
>         args=(search.get(),)
>     )
>     thread.setDaemon(True)
>     thread.start()

This tells Tkinter to run the check_state function 100 milliseconds later.

>     root.after(100, check_state)

As the -- aptly named ;) -- start_search() only starts the search without 
having to wait for the result it will only block the GUI for a moment that 
should normally be too short for the user to note.

You can think of the resulting script as two mini-programs that -- at least 
conceptually -- run indepently. If they access each other's data you can get 
an inconsistent state. The Queue class is written with precautions to avoid 
such problems. check_state() and Tkinter run in the main thread and only 
receive data from the thread executing fun() through the queue.

> def check_state():
>     while True:

          Look into the queue if there is a message from fun(). If there is
          return it, otherwise instead of waiting for the next message to
          arrive raise an exception immediately. Remember, if we stay here
          too long the GUI will lag.

>         try:
>             message = queue.get_nowait()
>         except Queue.Empty:

          Case (1) No pending messages, break out of the loop.

>             break

          Case (2) We have a message. Update the text of the state_info
          Label accordingly,

>         state_info["text"] = message

          then check if it's the last message we expect.

>         if message == "done":

              Yes it's the last message; leave check_state() without
              rescheduling it.

>             return

      We got here from the break statement. There are currently no messages, 
      but there may be later, so we ask Tkinter to run check_state again in
      100 milliseconds.

>     root.after(100, check_state)

PS: You can verify that you understood this by answering the question: what 
happens if the user hits the go-button while the second thread is still 
running. Hint: as written the script does not handle this correctly.



More information about the Python-list mailing list