103 lines
3.5 KiB
Python
103 lines
3.5 KiB
Python
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( ) |