diff --git a/gui/TkAsynThreads.py b/gui/TkAsynThreads.py new file mode 100644 index 0000000..19ddb6e --- /dev/null +++ b/gui/TkAsynThreads.py @@ -0,0 +1,103 @@ +import tkinter as tk +import time +import threading +import random +import queue + +class GuiPart: + def __init__(self, master, queue, endCommand): + self.queue = queue + # Set up the GUI + self.lbl1 = tk.Label(master, text='Counter 1') + self.lbl1.pack() + self.rnr = tk.StringVar() + self.en1 = tk.Entry(master,textvariable=self.rnr) + self.en1.pack() + self.btn_close = tk.Button(master, text='Close', command=endCommand) + self.btn_close.pack() + # Add more GUI stuff here depending on your specific needs + + def processIncoming(self): + """Handle all messages currently in the queue, if any.""" + while self.queue.qsize( ): + try: + msg = self.queue.get(0) + # Check contents of message and do whatever is needed. As a + # simple test, print it (in real life, you would + # suitably update the GUI's display in a richer fashion). + print(msg) + self.rnr.set(str(round(msg,2))) + except queue.Empty: + # just on general principles, although we don't + # expect this branch to be taken in this case + pass + +class ThreadedClient: + """ + Launch the main part of the GUI and the worker thread. periodicCall and + endApplication could reside in the GUI part, but putting them here + means that you have all the thread controls in a single place. + """ + def __init__(self, master): + """ + Start the GUI and the asynchronous threads. We are in the main + (original) thread of the application, which will later be used by + the GUI as well. We spawn a new thread for the worker (I/O). + """ + self.master = master + + # Create the queue + self.queue = queue.Queue( ) + + # Set up the GUI part + self.gui = GuiPart(master, self.queue, self.endApplication) + + # Set up the thread to do asynchronous I/O + # More threads can also be created and used, if necessary + self.running = 1 + self.thread1 = threading.Thread(target=self.workerThread1) + self.thread1.start( ) + + # Start the periodic call in the GUI to check if the queue contains + # anything + self.periodicCall( ) + + def periodicCall(self): + """ + Check every 200 ms if there is something new in the queue. + """ + self.gui.processIncoming( ) + if not self.running: + # This is the brutal stop of the system. You may want to do + # some cleanup before actually shutting it down. + import sys + ## sys.exit(1) + self.master.after(200, self.periodicCall) + + def workerThread1(self): + """ + This is where we handle the asynchronous I/O. For example, it may be + a 'select( )'. One important thing to remember is that the thread has + to yield control pretty regularly, by select or otherwise. + """ + while self.running: + # To simulate asynchronous I/O, we create a random number at + # random intervals. Replace the following two lines with the real + # thing. + time.sleep(rand.random( ) * 1.5) + msg = rand.random( ) + self.queue.put(msg) + + def endApplication(self): + self.running = 0 + + + +rand = random.Random( ) +root = tk.Tk( ) +root.geometry("500x300+200+200") +lf1 = tk.Label(root,text="Root Window") +lf1.pack() +client = ThreadedClient(root) + +root.mainloop( ) \ No newline at end of file diff --git a/gui/thread_one.py b/gui/thread_one.py new file mode 100644 index 0000000..1499119 --- /dev/null +++ b/gui/thread_one.py @@ -0,0 +1,25 @@ +from tkinter import * +import time +from random import randint +import threading + +def five_seconds(): + time.sleep(5) + my_label.config(text="5 sec up") + +def rando(): + rand_label.config(text=f'Random number {randint(1,100)}') + +root = Tk() +root.title("Jfs Threading Starts !!") +root.geometry("500x300+200+200") +my_label = Label(root,text="Hello there") +my_label.pack(pady=20) +my_button = Button(root,text="5 sec",command=threading.Thread(target=five_seconds).start()) +my_button.pack(pady=20) +my_button2 = Button(root,text="Pick random number",command=rando) +my_button2.pack(pady=20) +rand_label = Label(root,text="") +rand_label.pack(pady=20) + +root.mainloop() \ No newline at end of file