class GuiOutput: font = ('courier', 9, 'normal') # in class for all, self for one def __init__(self, parent=None): self.text = None if parent: self.popupnow(parent) # pop up now or on first write def popupnow(self, parent=None): # in parent now, Toplevel later if self.text: return self.text = ScrolledText(parent or Toplevel()) self.text.config(font=self.font) self.text.pack() def write(self, text): self.popupnow() self.text.insert(END, str(text)) self.text.see(END) self.text.update() # update gui after each line def writelines(self, lines): # lines already have '\n' for line in lines: self.write(line) # or map(self.write, lines)
class MyGUI: def __init__(self, reps=3): self.reps = reps # uses default Tk root self.text = ScrolledText() # save widget as state self.text.pack() threadChecker(self.text) # start thread check loop self.text.bind('<Button-1>', # 3.x need list for map, range ok lambda event: list(map(self.onEvent, range(6))) ) def onEvent(self, i): # code that spawns thread myname = 'thread-%s' % i startThread( action = self.threadaction, args = (i, ), context = (myname,), onExit = self.threadexit, onFail = self.threadfail, onProgress = self.threadprogress) # thread's main action def threadaction(self, id, progress): # what the thread does for i in range(self.reps): # access to object state here time.sleep(1) if progress: progress(i) # progress callback: queued if id % 2 == 1: raise Exception # odd numbered: fail # thread callbacks: dispatched off queue in main thread def threadexit(self, myname): self.text.insert('end', '%s\texit\n' % myname) self.text.see('end') def threadfail(self, exc_info, myname): # have access to self state self.text.insert('end', '%s\tfail\t%s\n' % (myname, exc_info[0])) self.text.see('end') def threadprogress(self, count, myname): self.text.insert('end', '%s\tprog\t%s\n' % (myname, count)) self.text.see('end') self.text.update() # works here: run in main thread
def threadaction(id, reps, progress): # what the thread does for i in range(reps): time.sleep(1) if progress: progress(i) # progress callback: queued if id % 2 == 1: raise Exception # odd numbered: fail # thread exit/progress callbacks: dispatched off queue in main thread def threadexit(myname): text.insert('end', '%s\texit\n' % myname) text.see('end') def threadfail(exc_info, myname): text.insert('end', '%s\tfail\t%s\n' % (myname, exc_info[0])) text.see('end') def threadprogress(count, myname): text.insert('end', '%s\tprog\t%s\n' % (myname, count)) text.see('end') text.update() # works here: run in main thread # make enclosing GUI and start timer loop in main thread # spawn batch of worker threads on each mouse click: may overlap text = ScrolledText() text.pack() threadChecker(text) # start thread loop in main thread text.bind( '<Button-1>', # 3.x need list for map, range ok lambda event: list(map(onEvent, range(6)))) text.mainloop() # pop-up window, enter tk event loop
def producer(id): for i in range(5): time.sleep(0.1) print('put') dataQueue.put('[producer id=%d, count=%d]' % (id, i)) def consumer(root): try: print('get') data = dataQueue.get(block=False) except queue.Empty: pass else: root.insert('end', 'consumer got => %s\n' % str(data)) root.see('end') root.after(250, lambda: consumer(root)) # 4 times per sec def makethreads(): for i in range(4): _thread.start_new_thread(producer, (i,)) if __name__ == '__main__': # main GUI thread: spawn batch of worker threads on each mouse click from Tkinter.scrolledtext import ScrolledText root = ScrolledText() root.pack() root.bind('<Button-1>', lambda event: makethreads()) consumer(root) # start queue check loop in main thread root.mainloop() # pop-up window, enter tk event loop
# thread's main action def threadaction(id, reps, progress): # what the thread does for i in range(reps): time.sleep(1) if progress: progress(i) # progress callback: queued if id % 2 == 1: raise Exception # odd numbered: fail # thread exit/progress callbacks: dispatched off queue in main thread def threadexit(myname): text.insert('end', '%s\texit\n' % myname) text.see('end') def threadfail(exc_info, myname): text.insert('end', '%s\tfail\t%s\n' % (myname, exc_info[0])) text.see('end') def threadprogress(count, myname): text.insert('end', '%s\tprog\t%s\n' % (myname, count)) text.see('end') text.update() # works here: run in main thread # make enclosing GUI and start timer loop in main thread # spawn batch of worker threads on each mouse click: may overlap text = ScrolledText() text.pack() threadChecker(text) # start thread loop in main thread text.bind('<Button-1>', # 3.x need list for map, range ok lambda event: list(map(onEvent, range(6))) ) text.mainloop() # pop-up window, enter tk event loop