Button Not Working in Tkinter Python Application - python

I am writing a python application using tkinter that plots weather data on a map. I am currently testing out my button that is supposed to plot the data on the map I created using basemap. However, when I run my program, my button does nothing. I defined my function that plots the data and called the function in the command attribute of my button. Anyone know what the problem could be?
import tkinter as tk
from tkinter import ttk
import tkinter.font as tkFont
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import numpy as np
import requests
lon = [-76.5152, -76.7311, -76.3055, -76.7277, -75.4714, -75.1652, -77.0011, -75.6624, -78.3947, -77.8600, -78.7583, -79.9959, -80.0851]
lat = [40.3295, 40.1998, 40.0379, 39.9626, 40.6023, 39.9526, 41.2412, 41.4090, 40.5187, 40.7934, 41.1210, 40.4406, 42.1292]
def current_weather():
key = '4a7a419e4e16e2629a4cedc37cbf7e50'
url = 'https://api.openweathermap.org/data/2.5/weather'
global observation
observation = []
for i in range(0,len(lon)):
params = {'lat': lat[i], 'lon': lon[i], 'appid': key, 'units': 'imperial'}
response = requests.get(url, params = params)
weather = response.json()
observation.append(round(weather['main']['temp']))
current_weather()
root = tk.Tk()
#place map on canvas
fig = Figure(figsize=(5, 4), dpi=100)
ax = fig.add_subplot(111)
map = Basemap(llcrnrlon=-80.5, llcrnrlat=39.8, urcrnrlon=-74.7, urcrnrlat=42.3,resolution='i',
lat_0 = 40., lon_0 = -80, ax = ax)
map.drawmapboundary(fill_color='#A6CAE0')
map.drawcounties(zorder = 20)
map.drawstates()
map.fillcontinents(color='#e6b800',lake_color='#A6CAE0')
def plot_data():
for i in range(0, len(lon)):
x,y = map(lon[i], lat[i])
ax.text(x, y, observation[i], fontsize = 7)
#create widgets
canvas = FigureCanvasTkAgg(fig, master = root)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
radiovalue = tk.IntVar()
temperature = tk.Radiobutton(root, text = "Plot current temperatures", variable = radiovalue, value = 1)
dewpoint = tk.Radiobutton(root, text = "Plot current dewpoints", variable = radiovalue, value = 2)
wind = tk.Radiobutton(root, text = "Plot current winds", variable = radiovalue, value = 3)
button = tk.Button(root, text = "Plot", command = plot_data)
#organize widgets
temperature.place(relx = 0.025, rely = 0.8)
dewpoint.place(relx = 0.385, rely = 0.8)
wind.place(relx = 0.675, rely = 0.8)
button.place(relx = 0.35, rely = 0.1)
root.mainloop()

Related

How to plot an automatic graph using mouse without clicking MATPLOTLIB

I'm looking to plot Data automatically using mouse without clicking From a DZT file.
i Created a program in order to plot data as you can see in this graph:
As you can see in this picture, x axes going from 0 to 3525 ans every x is a signal so i have more than 3500 signals making this graph.
for exemple if i want to see the signal of x=999, it looks like this.
what i want really to do is every time when i pass my mouse without clicking on the graph it should plot it's signal automatically .
i try to use a lot of methods but rally i dont know how to do it.
i'll be grateful for your help
this is my file:
https://www.grosfichiers.com/mvabGETFfna
This is my program:
from tkinter import *
from tkinter import messagebox, filedialog
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import os
from readgssi import readgssi
root = Tk()
root.title("IHM")
root.geometry("1000x800")
Resources_frame = LabelFrame(root, bd=2, relief=GROOVE, text="Conversion Area")
Resources_frame.place(x=5, y=5, width=250, height=80)
lbl_ra = Label(Resources_frame, text="Select your File ")
lbl_ra.grid(row=0, column=0, sticky=W)
lbl_ra = Label(Resources_frame, text="Convert Selected file ")
lbl_ra.grid(row=1, column=0, sticky=W)
NumberOfSimples = ''
DataAScan = ''
Data = ''
xData = ''
xAxes = ''
def ReadDZT():
file_path = filedialog.askopenfilename()
file_name, file_extension = os.path.splitext(file_path)
print(file_extension)
if file_extension == '.DZT':
messagebox.showinfo("INFO", "Your DZT File Has Been Selected Successfully")
hdr, arrs, gps = readgssi.readgssi(infile=file_path, verbose=True)
TimeRange = hdr['rhf_range']
Samples = hdr['rh_nsamp']
X_Axes = np.array(range(0, Samples))
xAxes = X_Axes[2::1]
df = pd.DataFrame(arrs[0])
Data = df.iloc[2::1, 0::1]
fig2 = plt.figure()
plt.plot(xAxes, Data[999])
plt.show()
fig = plt.figure()
plt.imshow(Data, aspect='auto', cmap='bone')
plt.show()
elif file_extension == '.csv':
messagebox.showinfo("INFO", "Your CSV File Has Been Selected Successfully")
df = pd.read_csv(file_path)
NumberOfSimples = df.iloc[2::1, 0]
Data = df.iloc[::1, ::1]
DataAScan = df.iloc[2::1, 999]
fig1 = plt.figure()
plt.plot(NumberOfSimples, DataAScan)
plt.show()
fig2 = plt.figure()
plt.imshow(Data, aspect='auto', cmap='bone')
plt.show()
else:
messagebox.showwarning("WARNING", "You Have Been Selected a Different Format")
# =============Resources Buttons================#
btn_rs = Button(Resources_frame, relief=GROOVE, padx=8, pady=1, text="Browse", command=ReadDZT).grid(row=0,
column=1)
root.mainloop()
As indicated in the previous question Ploting a graph automatically using mouse coordinate (and I think this question should have been an edit of it), the mouse motion can be monitored with plt.connect('motion_notify_event', mouse_move). The slice of Data to be plotted in fig2 simply corresponds to the x-coordinate of the mouse, that is Data[int(event.xdata)] in mouse_move(event).
Therefore, in mouse_move(event), you:
Clear the axis: ax2.clear() (where ax2 is the AxesSubplot object of fig2)
Plot the slice ax2.plot(self.xAxes, self.Data[int(event.xdata)])
Update the figure fig2.canvas.draw_idle()
However, I had issues with using simultaneously the matplotlib figures and the tkinter GUI because of the separate event loops. Therefore I embedded the figures in the tkinter GUI directly (see e.g. https://matplotlib.org/3.4.0/gallery/user_interfaces/embedding_in_tk_sgskip.html).
I also put the graph related code in a class to keep the loaded data in attributes to avoid using global variables.
import tkinter as tk
from tkinter import messagebox, filedialog
import pandas as pd
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.figure import Figure
import numpy as np
import os
from readgssi import readgssi
class Graphs(tk.Toplevel):
def __init__(self, master=None, **kw):
tk.Toplevel.__init__(self, master, **kw)
self.rowconfigure(0, weight=1)
self.rowconfigure(2, weight=1)
# data
self.Data = []
self.xData = []
self.xAxes = []
self.line = None
# figure1 : 2D data map
self.fig1 = Figure()
self.ax1 = self.fig1.add_subplot(111)
self.canvas1 = FigureCanvasTkAgg(self.fig1, self)
self.canvas1.draw()
self.canvas1.get_tk_widget().grid(sticky='ewsn')
self.toolbar1 = NavigationToolbar2Tk(self.canvas1, self, pack_toolbar=False)
self.toolbar1.grid(sticky="ew")
# figure 2: slice plot
self.fig2 = Figure()
self.ax2 = self.fig2.add_subplot(111)
self.canvas2 = FigureCanvasTkAgg(self.fig2, self)
self.canvas2.draw()
self.canvas2.get_tk_widget().grid(sticky='ewsn')
self.toolbar2 = NavigationToolbar2Tk(self.canvas2, self, pack_toolbar=False)
self.toolbar2.grid(sticky="ew")
# bind plotting to mouse motion
self.canvas1.mpl_connect('motion_notify_event', self.mouse_move)
def mouse_move(self, event):
x = event.xdata
if len(self.Data) and x is not None: # there is something to plot
self.ax2.clear()
x = int(x)
self.ax2.plot(self.xAxes, self.Data[x])
self.line.set_data([x, x], [len(self.Data), 0])
self.canvas1.draw_idle()
self.canvas2.draw_idle()
def readDZT(self):
file_path = filedialog.askopenfilename()
file_name, file_extension = os.path.splitext(file_path)
if file_extension == '.DZT':
messagebox.showinfo("INFO", "Your DZT File Has Been Selected Successfully")
hdr, arrs, gps = readgssi.readgssi(infile=file_path, verbose=True)
Samples = hdr['rh_nsamp']
X_Axes = np.array(range(0, Samples))
self.xAxes = X_Axes[2::1]
df = pd.DataFrame(arrs[0])
self.Data = df.iloc[2::1, 0::1]
# clear plots
self.ax1.clear()
self.ax2.clear()
# plot slice
self.ax2.plot(self.xAxes, self.Data[999])
self.canvas2.draw_idle()
# plot 2D map
self.ax1.imshow(self.Data, aspect='auto', cmap='bone')
self.line = self.ax1.plot([999, 999], [len(self.Data), 0], 'r')[0]
self.ax1.set_ylim(len(self.Data), 0)
self.canvas1.draw_idle()
else:
messagebox.showwarning("WARNING", "You Have Been Selected a Different Format")
root = tk.Tk()
root.title("IHM")
root.geometry("1000x800")
Resources_frame = tk.LabelFrame(root, bd=2, relief=tk.GROOVE, text="Conversion Area")
Resources_frame.place(x=5, y=5, width=250, height=80)
tk.Label(Resources_frame, text="Select your File ").grid(row=0, column=0, sticky=tk.W)
tk.Label(Resources_frame, text="Convert Selected file ").grid(row=1, column=0, sticky=tk.W)
graphs = Graphs(root)
btn_rs = tk.Button(Resources_frame, relief=tk.GROOVE, padx=8, pady=1, text="Browse",
command=graphs.readDZT).grid(row=0, column=1)
root.mainloop()

Unable to get desired output in a Tkinter window for a line graph

I'm new to coding and i'm trying to create a Tkinter window using Matplotlib classes that allows me to manipulate a line graph depicting the share prices for 4 companies over two years in a separate window, this is the code I've written:
from tkinter import *
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg,NavigationToolbar2Tk)
from matplotlib.backend_bases import key_press_handler
from matplotlib.figure import Figure
import pandas as pd
root = Tk ()
data = pd.read_csv('C:\\Users\\Admin\\Desktop\\shares.csv')
df = data.iloc[:,:5]
print(df)
print()
fig = Figure( figsize = (20,5) , dpi = 100 )
ax1 = fig.add_subplot()
df.plot('Date',figsize = (20,5), ax = ax1)
canvas = FigureCanvasTkAgg ( fig , root )
canvas.draw()
canvas.get_tk_widget().pack(side = TOP, fill = BOTH, expand = 1)
df.plot(kind = 'bar' , ax = ax1)
toolbar = NavigationToolbar2Tk(canvas, root)
toolbar.update()
canvas.get_tk_widget().pack(side = TOP, fill = BOTH, expand = 1)
def on_key(event):
print('You Pressed {}'.format(event.key))
key_press_handler(event, canvas, toolbar)
canvas.mpl_connect('key_press_event' , on_key)
def Quit():
root.quit()
root.destroy()
return
button = Button(root, text = 'QUIT' , command = Quit )
button.pack ()
root.mainloop()
This is the output I have obtained:
Whereas this is the desired graph:
I would appreciate any input as to how I can fix this, and make my code better.
Thanks :)
Try this it may work
df.plot(kind = 'line' , ax = ax1)
You are ploting bar and your expected output is a line graph

Is it possible to control a matplotlib graph using a Tkinter Scrollbar?

I would like to make an equivalent of the function FuncAnimation from matplotlib.animation, in which I could control the current plotted data using the scrollbar.
Say you have a data array which contains data points to be plotted at each time i. When using FuncAnimation, you first need to define a function ( here animate(i) ) which will be called for each time i = 1 to len(data[:,0]) :
def animate(i):
ax.plot(data[i,:])
anim = FuncAnimation(fig, animate, interval=100, frames=len(data[:,0]))
plt.draw()
plt.show()
but you cannot control the time i, like with a play/stop functionality. What I would like to do is to call the function animate(i), with i being the position of the scrollbar.
I found this example ( using the events from matplotlib:
https://matplotlib.org/3.2.1/users/event_handling.html )
but the mpl_connect doesn't have a "scrollbar_event".
import tkinter
from random import randint
import matplotlib as plt
import numpy as np
from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg, NavigationToolbar2Tk)
# Implement the default Matplotlib key bindings.
from matplotlib.backend_bases import key_press_handler
from matplotlib.figure import Figure
root = tkinter.Tk()
root.wm_title("Embedding in Tk")
#create figure
fig = Figure(figsize=(5, 4), dpi=100)
ax = fig.add_axes([0,0,1,1])
ax.imshow(np.array([[0,10],[23,40]]))
#create canvas with figure
canvas = FigureCanvasTkAgg(fig, master=root) # A tk.DrawingArea.
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)
def on_key_press(event):
ax.clear()
ax.imshow(np.array([[randint(0,30),randint(0,30)],[randint(0,30),randint(0,30)]]))
canvas.draw_idle()
key_press_handler(event, canvas)
print("you pressed {}".format(event.key))
#connect canvas to event function
canvas.mpl_connect("key_press_event", on_key_press)
def _quit():
root.quit() # stops mainloop
root.destroy() # this is necessary on Windows to prevent
# Fatal Python Error: PyEval_RestoreThread: NULL tstate
button = tkinter.Button(master=root, text="Quit", command=_quit)
button.pack(side=tkinter.BOTTOM)
tkinter.mainloop()
Actually the scroll functionality is given by matplotlib widgets !!
The example below works fine :
import matplotlib
import tkinter as Tk
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from myPytHeader import *
matplotlib.use('TkAgg')
root = Tk.Tk()
root.wm_title("Embedding in TK")
fig = plt.Figure(figsize=(8, 6))
canvas = FigureCanvasTkAgg(fig, root)
canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
nDt = nbLines("grid.dat")
nDx = nbGridPoints("grid.dat")
grid = np.zeros( (nDt,nDx) ) ; loadData("grid.dat", grid)
valu = np.zeros( (nDt,nDx) ) ; loadData("valu.dat", valu)
ax=fig.add_subplot(111)
fig.subplots_adjust(bottom=0.25)
ax_time = fig.add_axes([0.12, 0.1, 0.78, 0.03])
s_time = Slider(ax_time, 'Time', 0, nDt, valinit=0, valstep=1)
def update(val):
frame = int(s_time.val)
ax.clear()
ax.set(xlim=(-0.05, 1.05), ylim=(-0.05, 1.25))
ax.grid()
ax.scatter(grid[frame,:], valu[frame,:], color='b', marker='.')
fig.canvas.draw_idle()
s_time.on_changed(update)
Tk.mainloop()
After all these years I've found solutions to my problems here, I am in debt !!!
Here is the final solution I came with.
I hope it can be useful to someone someday somehow !!
import matplotlib
import numpy as np
import tkinter as tk
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from matplotlib.widgets import Slider
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
# load data
nDt = 1000
nDx = 400
grd = np.zeros( (nDt,nDx) )
val = np.zeros( (nDt,nDx) )
for t in np.arange(nDt):
for x in np.arange(nDx):
grd[t,x] = x / nDx
val[t,x] = (x / nDx) * (t/nDt) * np.sin(10 * 2*np.pi * (t-x)/nDt)
matplotlib.use('TkAgg')
root = tk.Tk()
root.wm_title("Embedding in TK")
fig = plt.Figure(figsize=(8, 6))
canvas = FigureCanvasTkAgg(fig, root)
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
ax=fig.add_subplot(111)
fig.subplots_adjust(bottom=0.25)
ax.set(xlim=(-0.05, 1.05), ylim=(-1.05, 1.05))
ax.grid()
scat = ax.scatter(grd[0,:], val[0,:], color='b', marker='.')
ax_time = fig.add_axes([0.12, 0.1, 0.78, 0.03])
s_time = Slider(ax_time, 'Time', 0, nDt, valinit=0, valstep=1)
i_anim = 0
i_relative = 0
i_current = 0
def updateGraph(i):
y_i = val[i,:]
scat.set_offsets(np.c_[grd[i,:], y_i])
def updateFromAnim(i):
global i_anim
global i_current
global i_relative
i_anim = i
i_current = i + i_relative
s_time.set_val(i_current)
updateGraph(i_current)
def updateFromScroll(val):
global i_anim
global i_current
global i_relative
i_relative = int(s_time.val) - i_anim
i_current = int(s_time.val)
updateGraph(i_current)
def onClick():
global anim_running
if anim_running:
anim.event_source.stop()
anim_running = False
else:
anim.event_source.start()
anim_running = True
start_button = tk.Button(root, text="START/STOP", command=onClick)
start_button.pack()
anim_running = True
anim = FuncAnimation(fig, updateFromAnim, interval=100, frames=nDt)
s_time.on_changed(updateFromScroll)
tk.mainloop()

Delete data from canvas in tkinter

how do i delete data from a figure when it is used in tktinter via FigureCanvasTkAgg?
I have tried to clear the figure with cla, clf and to delete the canvas with .delete, .clear.
My code: (If you have any advise how i can improve my code let me now. This is my first project in coding)
import tkinter as tk
from tkinter import *
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
#createplot
fig_CDF = Figure(figsize = (6, 5), facecolor = "white")
axis_CDF = fig_CDF.add_subplot(111)
canvas_CDF = FigureCanvasTkAgg(fig_CDF, master = window_main)
canvas_CDF._tkcanvas.pack(side = tk.TOP, fill = tk.BOTH, expand = 1)
canvas_CDF.get_tk_widget().place(x=400,y=50)
#plotdata
axis_CDF.plot(datax, datay, label = "data",marker=".", linestyle = "")
canvas_CDF.draw()
Thanks for your help!
In this code I added three buttons which shows three methods - all of them need canvas_CDF.draw() to redraw element in window.
first replaces data in plot and it removes points from chart but it still show axes.
second clears axis - so it remove data and set axis to 0..1
third clears figure - it removes even axis.
First version needs
plot = axis_CDF.plot(...)
to have access to data.
I use random only to create some data.
import tkinter as tk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import random
# --- functions ---
def replace_data():
datax = []
datay = []
#datax = range(10)
#datay = [x/10 for x in random.sample(range(10), 10)]
plot[0].set_data(datax, datay)
canvas_CDF.draw()
def clear_axis():
#axis_CDF.clear()
axis_CDF.cla()
canvas_CDF.draw()
def clear_figure():
fig_CDF.clear()
#fig_CDF.clf()
canvas_CDF.draw()
# --- main ---
window_main = tk.Tk()
datax = range(10)
datay = [x/10 for x in random.sample(range(10), 10)]
# create plot
fig_CDF = Figure(figsize=(6, 5), facecolor="white")
axis_CDF = fig_CDF.add_subplot(111)
canvas_CDF = FigureCanvasTkAgg(fig_CDF, master=window_main)
canvas_CDF._tkcanvas.pack(side='top', fill='both', expand=True)
canvas_CDF.get_tk_widget().pack()
# plot data
plot = axis_CDF.plot(datax, datay, label="data", marker=".", linestyle="")
canvas_CDF.draw()
# buttons
b = tk.Button(window_main, text='Replace data', command=replace_data)
b.pack()
b = tk.Button(window_main, text='Clear axis', command=clear_axis)
b.pack()
b = tk.Button(window_main, text='Clear figure', command=clear_figure)
b.pack()
window_main.mainloop()

matplotlib/tkinter how to get graph to show in tkinter entry

I have put together this piece of code that asks for an input in one Tkinter entry. I want the 3rd entry to be the graph, but I can't seem to get the graph to be put into window, rather than it's own.
Ignoring what goes into the first 2 rows of the Tkinter grid, I don't know where to go from here. I'm assuming I need to use some canvas which is why it's been imported but I don't know if I can reproduce this graph in that way.
#Import matplotlib modules
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
from numpy import arange, sin, pi
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.figure import Figure
#Put image under graph
img = plt.imread("graph.png")
fig, ax1 = plt.subplots()
ax1.imshow(img, extent=[-10,10,-10,10], aspect='equal')
#Set graph ranges
plt.ylim(-10, 10)
plt.xlim(-10, 10)
#Set axis & labels
ax1.set_xlabel('NEGATIVE')
ax1.set_ylabel('HAPPY')
ax2 = ax1.secondary_xaxis('top')
ax2.set_xlabel('POSITIVE')
ax3 = ax1.secondary_yaxis('right')
ax3.set_ylabel('SAD', rotation=270, labelpad=12.5)
#Remove ticks/values
for ax in (ax1, ax2, ax3):
ax.tick_params(left=False, labelleft=False, top=False, labeltop=False,
right=False, labelright=False, bottom=False, labelbottom=False)
#Calculate score
##TESTING##
import random
posNeg=0
hapSad=0
posNeg = random.randint(-12, 12)
hapSad = random.randint(-12, 12)
if posNeg < (-10):
posNeg = (-10)
if posNeg > 10:
posNeg = 10
if hapSad < (-10):
hapSad = (-10)
if hapSad > 10:
hapSad = 10
##TESTING##
#Plot point on graph
plt.plot([posNeg], [hapSad], marker = 'o', markersize = 15, color = 'red')
from tkinter import *
#testing input function
def print_input():
user_input = entry_1.get()
label_2["text"] = user_input
#window
window = Tk()
label_1 = Label(window, text = "What's your Twitter handle?")
entry_1 = Entry(window)
button_1 = Button(window, text = "go", command = print_input)
label_2 = Label(window)
label_1.grid(row = 0, column = 0)
entry_1.grid(row = 0, column = 1)
button_1.grid(row = 0, column = 2)
label_2.grid(row = 1, column = 0)
graph_1 = plt.show()
graph_1.grid(row = 3, column = 0)
window.mainloop()
#\window
You need to embed the graph using FigureCanvasTkAgg. It is a canvas on which matplotlib graphs can be drawn.
You have imported it, but have not used it. To display it, do the following:
graph_1 = FigureCanvasTkAgg(fig, master=window)
graph_1.get_tk_widget().grid(row = 3, column = 0)
graph_1.draw()

Categories

Resources