I’m building a tkinter GUI to retrieve incoming data from a device (through request) and appending them into a csv file, while having a preview of these data.
I use thread
but struggle to understand it properly, especially how to pause and restart it.
When I click on the start button, my threads are working properly. Once I try to click the stop streaming button, my stop_threads
variable change to 0, however, the while loop in my thread do not see this change. Do you know why?
Thanks a lot!
import tkinter as tk import threading from tkinter import ttk def init_csv(): pass # create my csv file here def clear_data(): tv1.delete(*tv1.get_children()) init_csv() def stream_data(): global stop_threads IP_Machine = IP_entry.get() while True: if stop_threads == 1: print('Stream') # retrieve incoming data from my device (through request) # appending them into a csv file if stop_threads == 0: print('Pause') # I want to pause this thread here def start_stream(): t1_stream.start() stream_label['text'] = 'Streaming...' button_start.destroy() # Create stop streaming button button_stop = tk.Button(main_frame, text="Stop Streaming", bg=Blue, fg=Bg_color, font='BOLD 12', command=stop_stream) button_stop.place(relx=0.2, rely=0.14, relwidth=0.15, relheight=0.07) def stop_stream(): stop_threads = 0 stream_label['text'] = '' # Create ReStart streaming button button_restart = tk.Button(main_frame, text="Start Streaming", bg=Blue, fg=Bg_color, font='BOLD 12', command=restart) button_restart.place(relx=0, rely=0.14, relwidth=0.15, relheight=0.07) def restart(): stop_threads = 1 stream_label['text'] = 'Streaming...' def curve(): # show live plot data with matplot Funcanimation pass def refresch_treeview(): tv1.delete(*tv1.get_children()) # define content of the treeview and refrech tv1.after(500, refresch_treeview) csv_path = 'C:/Users/b/Desktop/testfile.csv' init_csv() global stop_threads stop_threads = 1 # Multitasking definition t1_stream = threading.Thread(target=stream_data) t2_refresch = threading.Thread(target=refresch_treeview) # My Tkinter interface bellow root = tk.Tk() # Variables Bg_color = '#F2F2F2' Blue = '#045FB4' c_width = 1400 c_height = 700 # Template canvas = tk.Canvas(root, height=c_height, width=c_width, bg=Bg_color) canvas.pack() left_frame = tk.Frame(root, bg=Blue) left_frame.place(anchor='center', relx=0.05, rely=0.5, relwidth=0.002, relheight=0.9) right_frame = tk.Frame(root, bg=Blue) right_frame.place(anchor='center', relx=0.95, rely=0.5, relwidth=0.002, relheight=0.9) top_frame = tk.Frame(root, bg=Blue) top_frame.place(anchor='center', relx=0.5, rely=0.05, relwidth=0.9, relheight=0.004) bottom_frame = tk.Frame(root, bg=Blue) bottom_frame.place(anchor='center', relx=0.5, rely=0.95, relwidth=0.9, relheight=0.004) main_frame = tk.Frame(root, bg=Bg_color) main_frame.place(anchor='center', relx=0.5, rely=0.5, relwidth=0.8, relheight=0.8) # Title title = tk.Label(root, text='Data analysis', height=2, width=20, font='bold 18') title.place(anchor='center', relx=0.50, rely=0.05) # ENTRIES Definition # Machine IP IP_frame = tk.Frame(main_frame, bg=Bg_color) IP_frame.place(relx=0, rely=0.05, relwidth=0.35, relheight=0.05) IP_label = tk.Label(IP_frame, text='2000Xc IP address : ', font='12') IP_label.pack(side='left', fill='y') IP_entry = tk.Entry(IP_frame, width=22, font='12') IP_entry.pack(side='right', fill='y') # Streaming runing label stream_label = tk.Label(main_frame, font='10', text='') stream_label.place(anchor='w', relx=0, rely=0.45, relwidth=0.1, relheight=0.06) # BUTTONS Definition # Start streaming button button_start = tk.Button(main_frame, text="Start Streaming", bg=Blue, fg=Bg_color, font='BOLD 12', command=start_stream) button_start.place(relx=0, rely=0.14, relwidth=0.15, relheight=0.07) # Clear data button_clear = tk.Button(main_frame, text="Clear data", bg=Blue, fg=Bg_color, font='BOLD 10', command=clear_data) button_clear.place(relx=0.92, rely=0.9, relwidth=0.08, relheight=0.06) # Show graph button button_graph = tk.Button(main_frame, text="Show curves", bg=Blue, fg=Bg_color, font='BOLD 10', command=curve) button_graph.place(relx=0.6, rely=0.35, relwidth=0.1, relheight=0.05) # csv preview preview_frame = tk.Frame(main_frame, bg=Bg_color) preview_frame.place(relx=0, rely=0.5, relwidth=1, relheight=0.4) tv1 = ttk.Treeview(preview_frame) tv1.place(relheight=0.95, relwidth=1) # set the height and width of the widget to 100% of its container (frame1). # scroll preview treescrolly = tk.Scrollbar(preview_frame, orient="vertical", command=tv1.yview) # command means update the yaxis view of the widget treescrollx = tk.Scrollbar(preview_frame, orient="horizontal", command=tv1.xview) # command means update the xaxis view of the widget tv1.configure(xscrollcommand=treescrollx.set, yscrollcommand=treescrolly.set) # assign the scrollbars to the Treeview Widget treescrollx.pack(side="bottom", fill="x") # make the scrollbar fill the x axis of the Treeview widget treescrolly.pack(side="right", fill="y") # make the scrollbar fill the y axis of the Treeview widget t2_refresch.start() root.mainloop()
Advertisement
Answer
You have to change only one thing. You need to define stop_threads as global inside the functions. Python then knows that you are referring to the global variable instead of creating a new variable inside the local function scope.
import tkinter as tk import threading from tkinter import ttk def init_csv(): pass # create my csv file here def clear_data(): tv1.delete(*tv1.get_children()) init_csv() def stream_data(): global stop_threads IP_Machine = IP_entry.get() while True: if stop_threads == 1: print('Stream') # retrieve incoming data from my device (through request) # appending them into a csv file if stop_threads == 0: print('Pause') # I want to pause this thread here def start_stream(): t1_stream.start() stream_label['text'] = 'Streaming...' button_start.destroy() # Create stop streaming button button_stop = tk.Button(main_frame, text="Stop Streaming", bg=Blue, fg=Bg_color, font='BOLD 12', command=stop_stream) button_stop.place(relx=0.2, rely=0.14, relwidth=0.15, relheight=0.07) def stop_stream(): global stop_threads stop_threads = 0 stream_label['text'] = '' # Create ReStart streaming button button_restart = tk.Button(main_frame, text="Start Streaming", bg=Blue, fg=Bg_color, font='BOLD 12', command=restart) button_restart.place(relx=0, rely=0.14, relwidth=0.15, relheight=0.07) def restart(): global stop_threads stop_threads = 1 stream_label['text'] = 'Streaming...' def curve(): # show live plot data with matplot Funcanimation pass def refresch_treeview(): tv1.delete(*tv1.get_children()) # define content of the treeview and refrech tv1.after(500, refresch_treeview) csv_path = 'C:/Users/b/Desktop/testfile.csv' init_csv() stop_threads = 1 # Multitasking definition t1_stream = threading.Thread(target=stream_data) t2_refresch = threading.Thread(target=refresch_treeview) # My Tkinter interface bellow root = tk.Tk() # Variables Bg_color = '#F2F2F2' Blue = '#045FB4' c_width = 1400 c_height = 700 # Template canvas = tk.Canvas(root, height=c_height, width=c_width, bg=Bg_color) canvas.pack() left_frame = tk.Frame(root, bg=Blue) left_frame.place(anchor='center', relx=0.05, rely=0.5, relwidth=0.002, relheight=0.9) right_frame = tk.Frame(root, bg=Blue) right_frame.place(anchor='center', relx=0.95, rely=0.5, relwidth=0.002, relheight=0.9) top_frame = tk.Frame(root, bg=Blue) top_frame.place(anchor='center', relx=0.5, rely=0.05, relwidth=0.9, relheight=0.004) bottom_frame = tk.Frame(root, bg=Blue) bottom_frame.place(anchor='center', relx=0.5, rely=0.95, relwidth=0.9, relheight=0.004) main_frame = tk.Frame(root, bg=Bg_color) main_frame.place(anchor='center', relx=0.5, rely=0.5, relwidth=0.8, relheight=0.8) # Title title = tk.Label(root, text='Data analysis', height=2, width=20, font='bold 18') title.place(anchor='center', relx=0.50, rely=0.05) # ENTRIES Definition # Machine IP IP_frame = tk.Frame(main_frame, bg=Bg_color) IP_frame.place(relx=0, rely=0.05, relwidth=0.35, relheight=0.05) IP_label = tk.Label(IP_frame, text='2000Xc IP address : ', font='12') IP_label.pack(side='left', fill='y') IP_entry = tk.Entry(IP_frame, width=22, font='12') IP_entry.pack(side='right', fill='y') # Streaming runing label stream_label = tk.Label(main_frame, font='10', text='') stream_label.place(anchor='w', relx=0, rely=0.45, relwidth=0.1, relheight=0.06) # BUTTONS Definition # Start streaming button button_start = tk.Button(main_frame, text="Start Streaming", bg=Blue, fg=Bg_color, font='BOLD 12', command=start_stream) button_start.place(relx=0, rely=0.14, relwidth=0.15, relheight=0.07) # Clear data button_clear = tk.Button(main_frame, text="Clear data", bg=Blue, fg=Bg_color, font='BOLD 10', command=clear_data) button_clear.place(relx=0.92, rely=0.9, relwidth=0.08, relheight=0.06) # Show graph button button_graph = tk.Button(main_frame, text="Show curves", bg=Blue, fg=Bg_color, font='BOLD 10', command=curve) button_graph.place(relx=0.6, rely=0.35, relwidth=0.1, relheight=0.05) # csv preview preview_frame = tk.Frame(main_frame, bg=Bg_color) preview_frame.place(relx=0, rely=0.5, relwidth=1, relheight=0.4) tv1 = ttk.Treeview(preview_frame) tv1.place(relheight=0.95, relwidth=1) # set the height and width of the widget to 100% of its container (frame1). # scroll preview treescrolly = tk.Scrollbar(preview_frame, orient="vertical", command=tv1.yview) # command means update the yaxis view of the widget treescrollx = tk.Scrollbar(preview_frame, orient="horizontal", command=tv1.xview) # command means update the xaxis view of the widget tv1.configure(xscrollcommand=treescrollx.set, yscrollcommand=treescrolly.set) # assign the scrollbars to the Treeview Widget treescrollx.pack(side="bottom", fill="x") # make the scrollbar fill the x axis of the Treeview widget treescrolly.pack(side="right", fill="y") # make the scrollbar fill the y axis of the Treeview widget t2_refresch.start() root.mainloop()