Ваш код работает для меня, если я использую root.after()
вместо многопоточности.
Возможно, в большинстве сред GUI поток должен (или не может) изменить элемент в графическом интерфейсе.
На моемкомпьютерный код с завершением потоков работает, когда я нажимаю кнопку запуска потока.
Я запускаю plotter
, который не использует while
и sleep
, но after(1000, plotter)
, чтобы запустить его снова через 1000 мс (1 с)
from tkinter import *
from random import randint
# these two imports are important
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
continuePlotting = False
def change_state():
global continuePlotting
if continuePlotting == True:
continuePlotting = False
else:
continuePlotting = True
def data_points():
f = open("data.txt", "w")
for i in range(10):
f.write(str(randint(0, 10))+'\n')
f.close()
f = open("data.txt", "r")
data = f.readlines()
f.close()
l = []
for i in range(len(data)):
l.append(int(data[i].rstrip("\n")))
return l
def app():
# initialise a window.
root = Tk()
root.config(background='white')
root.geometry("1000x700")
lab = Label(root, text="Live Plotting", bg = 'white').pack()
fig = Figure()
ax = fig.add_subplot(111)
ax.set_xlabel("X axis")
ax.set_ylabel("Y axis")
ax.grid()
graph = FigureCanvasTkAgg(fig, master=root)
graph.get_tk_widget().pack(side="top",fill='both',expand=True)
def plotter():
if continuePlotting:
ax.cla()
ax.grid()
dpts = data_points()
ax.plot(range(10), dpts, marker='o', color='orange')
graph.draw()
root.after(1000, plotter)
def gui_handler():
change_state()
plotter()
b = Button(root, text="Start/Stop", command=gui_handler, bg="red", fg="white")
b.pack()
root.mainloop()
if __name__ == '__main__':
app()
РЕДАКТИРОВАТЬ: в новом коде вы не запускаете цикл, поэтому вам не нужны потоки или after()
Но у вас естьдругие основные проблемы:
У вас неправильный абзац и mainloop()
находится за пределами app()
- выполняется до app()
В предыдущей версии plotter
был внутри app()
- еслион вам нужен снаружи, тогда у вас есть проблемы с локальными переменными - такими как ax
- и вы должны использовать global
, чтобы иметь доступ к этим переменным в другой функции.Или вы должны запустить функцию с этими значениями в качестве аргументов - т.е.plotter(ax, wcss, graph)
Эта версия использует global
, и она работает для меня.У меня нет вашего CSV, и я не хочу запускать sklearn
, поэтому я поместил некоторые поддельные данные.
from tkinter import *
# these four imports are important
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
def plot():
# Importing Libraries
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import sys
# Importing the Batsmen Dataset
# dataset = pd.read_csv('Batsmen/Batsmen.csv')
dataset = pd.DataFrame({
'a': range(10),
'b': range(10),
'c': range(10),
'd': range(10),
'e': range(10),
'f': range(10),
'g': range(10),
})
X = dataset.iloc[:, [1, 2, 3, 4, 5, 6]].values
# Using Elbow Method to find the optimal number of Clusters
from sklearn.cluster import KMeans
global wcss
wcss = range(1, 11)
#wcss = []
# for i in range(1, 11):
# kmeans = KMeans(n_clusters=i, init='k-means++', n_init=10, max_iter=300, random_state=0)
# kmeans.fit(X)
# wcss.append(kmeans.inertia_)
def plotter():
global wcss
global ax
global graph
ax.cla()
ax.grid()
dpts = plot()
ax.plot(range(1, 11), wcss, marker='o', color='orange')
graph.draw()
def gui_handler():
plotter()
def app():
global ax
global graph
# initialise a window.
root = Tk()
root.config(background='white')
root.geometry("1000x700")
lab = Label(root, text="Live Plotting", bg = 'white').pack()
fig = Figure()
ax = fig.add_subplot(111)
ax.set_title('The Elbow Method')
ax.set_xlabel('Number of Clusters')
ax.set_ylabel('WCSS')
ax.grid()
graph = FigureCanvasTkAgg(fig, master=root)
graph.get_tk_widget().pack(side="top",fill='both',expand=True)
b = Button(root, text="Start/Stop", command=gui_handler, bg="red", fg="white")
b.pack()
root.mainloop()
if __name__ == '__main__':
app()