Я создаю графический интерфейс tkinter для получения входящих данных с устройства (через запрос) и добавляю их в файл csv, имея при этом предварительный просмотр этих данных.
Я использую thread
, но с трудом понимаю его правильно, особенно как приостановить и перезапустить его.
Когда я нажимаю кнопку «Пуск», мои потоки работают правильно. Как только я пытаюсь нажать кнопку остановки потоковой передачи, моя переменная stop_threads
изменяется на 0, однако цикл while в моем потоке не видит этого изменения. Ты знаешь почему?
Большое спасибо!
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()
Эй, я добавляю в код детали, которые знают, что их можно запускать как есть. Моя проблема в том, что если вы нажмете кнопку запуска, она напечатает «Поток», что хорошо. Однако после этого, когда нажата кнопка «остановить поток», он продолжает печатать «Поток» вместо «Пауза».
Вы должны изменить только одну вещь. Вам нужно определить stop_threads как глобальный внутри функций. Затем Python знает, что вы ссылаетесь на глобальную переменную, а не создаете новую переменную внутри области действия локальной функции.
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()
О, чувак, большое спасибо, я боролся с этим в течение 2 дней, и это была только эта мелочь.. Мне жаль, что я побеспокоил вас, ребята, из-за такой маленькой проблемы, но это помогает мне каждый раз узнавать больше! Спасибо. большое спасибо за поддержку, теперь работает нормально!
Добро пожаловать. Вот для чего нужен stackoverflow :)
Эй, Батист, вы получите лучшие ответы, если предоставите нам минимальный рабочий пример. Я не могу воспроизвести это напрямую, так как отсутствуют импорт и переменные.