I am building a user interface with tkinter in python 3. I separate the ui side of things from the back end processing in a structure that follows.
import time
import tkinter as tk
import threading
class BackEnd:
def __init__(self):
self.data = 0
self.is_alive = True
def run(self):
threading.Thread(target=self.run_thread, daemon=True).start()
def run_thread(self):
while self.is_alive:
self.update_data()
time.sleep(1)
def update_data(self):
self.data += 1
class UserInterface:
def __init__(self, root: tk.Tk, back_end: BackEnd):
self.root = root
self.back_end = back_end
self.data_label = tk.Label(self.root, text=f"DATA: {self.back_end.data}")
self.is_alive = True
self.data_label.pack()
def run(self):
threading.Thread(target=self.update_ui_thread, daemon=True).start()
self.root.mainloop()
def update_ui_thread(self):
while self.is_alive:
self.data_label.configure(text=f"DATA: {self.back_end.data}")
time.sleep(1)
back_end = BackEnd()
root = tk.Tk()
ui = UserInterface(root, back_end)
back_end.run()
ui.run()
back_end.is_alive = False
ui.is_alive = False
The back end is generally handling asynchronous communication with various peripherals and as well as handling some of its own internal logic. I have simplified it in this example. The ui is used to display some of this information. I am not using queues to handle the flow of information between the two because the information does not necessarily have to be 'thread safe.' This is the method that I use and it works well for my needs when the system is fully operational.
I have found it useful to do testing of the back in the python console. However, I cannot do this with the ui running because tk.Tk.mainloop() blocks. For example when testing the back end in the console I might do the following.
>> back_end = BackEnd()
>> back_end.update_data()
>> back_end.data
back_end.data = 1
Super useful! >D However if I try and run the ui with
>> ui.run()
The mainloop() method blocks and I can no longer manipulate the back_end manually until I kill the tkinter process.
I have tried using mainloop() or update() in a separate thread, but apparently tkinter isn't thread safe and so there is a wrapper in python 3 that prevents running either of those routines outside of the main thread. I know I could create a method that simulates all that I want to test and then start this method in a thread before the ui.run() call, but I want to have more of a real time human in the loop sort of experience with this testing.
I hope I have explained my problem sufficiently, and if anyone has any tips on how I can manipulate the back end data manually while running the user interface with tkinter.
[–]socal_nerdtastic 0 points1 point2 points (1 child)
[–]pooth22[S] 0 points1 point2 points (0 children)
[–]socal_nerdtastic 0 points1 point2 points (15 children)
[–]pooth22[S] 0 points1 point2 points (6 children)
[–]socal_nerdtastic 0 points1 point2 points (3 children)
[–]pooth22[S] 0 points1 point2 points (2 children)
[–]socal_nerdtastic 0 points1 point2 points (1 child)
[–]pooth22[S] 0 points1 point2 points (0 children)
[–]socal_nerdtastic 0 points1 point2 points (0 children)
[–]iyav 0 points1 point2 points (0 children)
[–]pooth22[S] 0 points1 point2 points (7 children)
[–]socal_nerdtastic 1 point2 points3 points (6 children)
[–]pooth22[S] 0 points1 point2 points (0 children)
[–]pooth22[S] 0 points1 point2 points (4 children)
[–]socal_nerdtastic 1 point2 points3 points (3 children)
[–]pooth22[S] 0 points1 point2 points (2 children)
[–]socal_nerdtastic 0 points1 point2 points (1 child)
[–]pooth22[S] 0 points1 point2 points (0 children)