Domanda

My tkinter app has 2 threads (I need them) and I found on stackoverflow a wonderful function tkloop(), which is made for tkinter-only-one-main-thread; it uses Queue. It does show tkMessagebox when I do this:

self.q.put((tkMessageBox.askyesno,("Cannot download it", "Download \"" + tag +"\" via internet site"),{}, self.q1 ))

But when I made my own function, it somehow doesn't execute the function

self.q.put((self.topleveldo,(resultlist),{},None))

There's only one class App:

self.q=Queue()
def tkloop(self):
    try:
        while True:
            f, a, k, qr = self.q.get_nowait()
            print f
            r = f(*a,**k)

            if qr: qr.put(r)
    except:
        pass
    self.okno.after(100, self.tkloop)
def topleveldo(resultlist):
    print ("executed - actually this never prints")
    self.choice=Toplevel()
    self.choices=Listbox(self.choice)
    for result in resultlist:
        self.choices.insert(END,str(result))
    choosebutton=Button(text="Vybrat",command=self.readchoice)
def readchoice(self):
    choice=int(self.choices.curselection())
    self.choice.destroy()
    self.q1.put(choice)

another code in a method in class App, run by the second thread:

def method(self):
    self.q1=Queue()
    self.q.put((self.topleveldo,(resultlist),{},None))
    print ("it still prints this, but then it waits forever for q1.get, because self.topleveldo is never executed")
    choice=self.q1.get()
È stato utile?

Soluzione

Log errors in the tkloop exception handler - right now you don't know if the call to topleveldo failed (it probably did). The problem is that (1) (resultlist) is just resultlist, not a tuple with 1 argument like topleveldo expects. And (2) tkloop only puts a response if the 4th parameter in the message is a queue. You can fix it with:

self.q.put((self.topleveldo,(resultlist,),{},self.q1))

Added:

tkloop should always return a message, even if it caught an exception, so that callers can reliably call q.get() to get a response. One way to do this is to return the exception that the called program raised:

def tkloop(self):
    while True:
        try:
            f, a, k, qr = self.q.get_nowait()
            print f
            r = f(*a,**k)
            if qr: 
                qr.put(r)
            del f,a,k,qr
    except Exception, e:
        if qr:
            try:
                qr.put(e)
            except:
                # log it
                pass
    self.okno.after(100, self.tkloop)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top