简体   繁体   中英

tkinter python button run in background command

I'm mucking about with Tkinter and Python. I have a basic gui with a couple of buttons on, one button goes away and does something that takes some amount of time, which is variable. The problem is when I hit this button the whole of my gui locks up/ doesnt show correctly - I guess because its trying to do these things that take some amount of time and its blocking the gui.

I have looked into threading and queues, but I can't figure it out. I think I need to fire off my lookup method on a thread and then queue the results as they come back and update the listbox as there coming back?

I'm on windows if this makes a difference to the way I use threads.

Kind Regards

david

Basic code below.

class Search:

        def __init__(self, master):

            self.seeds = []

            frame = Frame(master, width=700, height=500)
            frame.pack_propagate(0)
            frame.pack(expand=YES, fill=BOTH)

            #
            # Search results
            #
            l2 = Label(frame, text="results")
            l2.pack(anchor=W)
            self.resultfield = Listbox(frame, selectmode=BROWSE)
            self.resultfield.grid(row=3, column=1, sticky=N+W+S+E, columnspan=3)
            self.resultfield.pack(fill=BOTH)

            frame1 = Frame(frame)
            frame1.pack()


            # Button to action the search
            self.getSearchbut = Button(frame1, text="Do Search", command=self.getSearch)
            self.getSearchbut.grid(row=1, column=2)
            self.getSearchbut.pack()

        def getSearch(self):


            sa = SearchApi(self.seeds)

            results = sa.lookup(self)


            for result in results:
                self.resultfield.insert(END, user)

        def putCSV(self):
            print "put the csv files"

class SearchApi: 

        def __init__(self, seeds):
            self.seeds = seeds

        def lookup(self):
            results = []
                # I do something here that takes a while
                return results




if __name__ == "__main__":

    root = Tk()
    root.title("Search")

    app = Search(root)

    root.mainloop()

Using threads is simple, really. All you have to do is to import the Thread class:

from threading import Thread

and change the getSearch function to look like this:

def getSearch(self):
    t= Thread(target=self.search)#this should work, in case it doesn't, try "t= Thread(target=Search.getSearch,args=[self])" instead.
    t.start()

def search(self):
    sa = SearchApi(self.seeds)
    results = sa.lookup(self)
    for result in results:
        self.resultfield.insert(END, user)

That should be all you need to do, since I'm pretty sure Tkinter is thread safe. In case it isn't, you'll have to make one thread that inserts the other thread's results into the text widget.

Also, this is Python. It doesn't matter if you're on windows or not :D

I had this same issue until just today! Your issue is that the mainloop of Tkinter is interfering with your task loop. I had to take all classes out of my program and use only functions. The button you use will toggle a variable which then starts up the loop task.

Then solution is simple, after about a week of looking (this is a condensed version of my code):

   scnBtn = Button(Frame, text="Update", command=readIt)
   scnBtn.pack()


def readIt(): ## this is the variable the button changes
    global read

    read = 1
    TK.after(0, readFile) ##this is how you make sure the GUI doesn't freeze up

def readFile(): ## this is the task you want the button to do
    global read

    if read == 1:

        "your task"

        if "task is over"

            read = 0

    if read == 1:
        TK.after(0, readFile) ## this will keep the task going until its done.

Hope this helped!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM