# How To Visualize A Matplotlib Prediction Using A Tkinter GUI?

## 21 April 2019 - 1 answer

I have a scenario where I made a prediction on a particular dataset. Now I want to visualize that predicted graph using Tkinter.

My Machine Learning Model looks as below which consists of a graph:

``````# Importing Libraries
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import sys

# Importing the Batsmen Dataset
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
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_)
plt.plot(range(1, 11), wcss)
plt.title('The Elbow Method')
plt.xlabel('Number of Clusters')
plt.ylabel('WCSS')
plt.show()
``````

I tried as shown below:

``````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
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
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_)

root = Tk()

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

def plotter():
ax.cla()
ax.grid()
dpts = plot()
ax.plot(range(1, 11), wcss, marker='o', color='orange')
graph.draw()
time.sleep(1)

def gui_handler():

b = Button(root, text="Start/Stop", command=gui_handler, bg="red", fg="white")
b.pack()

root.mainloop()

if __name__ == '__main__':
app()
``````

But its not working out!

I just want to show the prediction on the Tkinter GUI and when I press the predict button in the GUI, I want the graph to be displayed inside the GUI canvas. So, Can anyone please help me in doing the same.

You code works for me if I use `root.after()` instead of threading.

Probably in most GUI frameworks thread should (or can't) change element in GUI.

On my computer yoru code with threading ends work when I press button which runs thread.

I run `plotter` whic doesn't use `while` and `sleep` but `after(1000, plotter)` to run it again after 1000ms (1s)

``````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")
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.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()
``````

EDIT: in new code you don't run loop so you don't need threading or `after()`

But you have other basic problems:

You have wrong indention and `mainloop()` is outside `app()` - it is executed before `app()`

In previous version `plotter` was inside `app()` - if you need it outside then you have problem with local variables - like `ax` - and you have to use `global` to have access to these variables in other function. Or you have to run function with this values as arguments - ie. `plotter(ax, wcss, graph)`

This version use `global` and it works for me. I don't have your CSV and I don't want to run `sklearn` so I put some fake data.

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