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()
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()