Evening,
I want to insert a data point externally into an existing plot (f(x) = x, g(x) = x**2). To do this, the x and y coordinates can be entered in entry fields. The user can then press a button to insert the point.
Assuming a data point (x1, y1) is inserted and the user trys to enter a new data point (x2,y2). In this case the GUI should only display the curves (f(x), g(x)) and the point (x2, y2). The last point (x1,y1) should be deleted.
My solution only partially works: Additional points (x,y) can be created, but the old ones are not deleted...
Does any of you know an approach to solve the problem described above.
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import tkinter as tk
import numpy as np
fig = Figure(figsize = (9, 6), facecolor = "white")
axis = fig.add_subplot(111)
x_values = np.array([1,2,3,4,5,6,7])
axis.plot(x_values, x_values, "-r")
axis.plot(x_values, x_values ** 2, "--g")
axis.grid()
root = tk.Tk()
Label(root, text = "x =" ).grid(row = 0, column = 0)
Label(root, text = "y =" ).grid(row = 1, column = 0)
x = DoubleVar()
y = DoubleVar()
x_entry = Entry(root, textvariable = x).grid(row = 0, column = 1)
y_entry = Entry(root, textvariable = y).grid(row = 1, column = 1)
def plotgraphs():
axis.plot(x.get(), y.get(), "ko")
canvas = FigureCanvasTkAgg(fig, master = root)
canvas._tkcanvas.grid(row = 2, column = 1)
Button(root, text = "New Graphs", command = plotgraphs).grid(row = 0, column = 2)
canvas = FigureCanvasTkAgg(fig, master = root)
canvas._tkcanvas.grid(row = 2, column = 1)
root.mainloop()
You need to delete existing point to get the desired behavior. Below would do - what you are looking for. I did enhanced it a bit.
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import tkinter as tk
import numpy as np
from tkinter import *
fig = Figure(figsize = (9, 6), facecolor = "white")
axis = fig.add_subplot(111)
x_values = np.array([1,2,3,4,5,6,7])
axis.plot(x_values, x_values, "-r", label = 'f(X) = x')
axis.plot(x_values, x_values ** 2, "--g", label = 'f(x) = x\N{SUPERSCRIPT TWO}')
axis.grid()
axis.legend()
root = tk.Tk()
Label(root, text = "x =" ).grid(row = 0, column = 0)
Label(root, text = "y =" ).grid(row = 1, column = 0)
x = DoubleVar()
y = DoubleVar()
x_entry = Entry(root, textvariable = x).grid(row = 0, column = 1)
y_entry = Entry(root, textvariable = y).grid(row = 1, column = 1)
def plotgraphs():
if (len(axis.lines)) == 3: # Count existing plotted lines and delete if already existing
del (axis.lines[2])
axis.plot(x.get(), y.get(), "ko", label = 'Input point')
else:
axis.plot(x.get(), y.get(), "ko", label = 'Input point')
axis.legend()
canvas = FigureCanvasTkAgg(fig, master = root)
canvas._tkcanvas.grid(row = 2, column = 1)
Button(root, text = "New Graphs", command = plotgraphs).grid(row = 0, column = 2)
canvas = FigureCanvasTkAgg(fig, master = root)
canvas._tkcanvas.grid(row = 2, column = 1)
root.mainloop()
Related
I'm using grid_remove() and grid() command to hide/show the widget but the result is the other widget is move out of the original position.
How to hide/show the widget without moving widget
Example:
from tkinter import *
from tkinter import ttk
GUI = Tk()
GUI.title("myTest")
GUI.geometry("700x700")
Nameget = StringVar()
Priceget = StringVar()
Quantityget = StringVar()
Unitget = StringVar()
Partnumget = StringVar()
L_Partnum = ttk.Label(GUI, text = 'Part number')
L_Partnum.grid(row = 0, column = 0)
L_namme = ttk.Label(GUI, text = 'Name')
L_namme.grid(row = 0, column = 1)
L_quan = ttk.Label(GUI, text = 'Quantity')
L_quan.grid(row = 1, column = 2)
L_quan.grid_remove()
L_price = ttk.Label(GUI, text = 'Price')
L_price.grid(row = 3, column = 3)
E_partnum = ttk.Entry(GUI, textvariable = Partnumget)
E_partnum.grid(row = 1, column = 0)
E_namme = ttk.Entry(GUI,textvariable = Nameget)
E_namme.grid(row = 1, column = 1)
E_unit = ttk.Entry(GUI,textvariable = Unitget)
E_quan = ttk.Entry(GUI,textvariable = Quantityget)
E_quan.grid(row = 2, column = 2)
E_quan.grid_remove()
E_price = ttk.Entry(GUI,textvariable = Priceget)
E_price.grid(row = 4, column = 3)
I_check_vat = IntVar()
def d_check_vat_1():
E_partnum.focus()
if I_check_vat.get() == 1:
L_quan.grid()
E_quan.grid()
elif I_check_vat.get() == 0:
L_quan.grid_remove()
E_quan.grid_remove()
C_CHECK_VAT = ttk.Checkbutton(GUI, text="click here to see the result", variable=I_check_vat, command=d_check_vat_1)
C_CHECK_VAT.grid(row = 5, column = 0)
GUI.mainloop()
Before clicking:
After clicking:
image with the expected output:
The problem is grid() does not take up empty space by default, it gives the last empty row/col to the widget(if previous rows before it are empty).
So what you can do is, set minimum space for your column and row so that those space will remain empty, so change your function to:
def d_check_vat_1():
E_partnum.focus()
if I_check_vat.get():
L_quan.grid(row=2, column=2)
E_quan.grid(row=3, column=2)
width = E_quan.winfo_reqwidth() # Get widget width
height = L_quan.winfo_reqheight() # Get widget height
GUI.rowconfigure(2,minsize=height) # Now apply the values
GUI.rowconfigure(3,minsize=height)
GUI.columnconfigure(2,minsize=width)
else:
L_quan.grid_remove()
E_quan.grid_remove()
Now its dynamic as well, it takes the width of widget and applies that as the minsize of that row so that row will have that empty space.
I have a Tkinter gui that works when I run it from vs code. When I then close it and press 'run' again on vs code I only see the filename appear in the vs code terminal.
At the moment I have to close vs code and re-open it to run the gui.
After some hints from Cool Cloud it showed that when I ran the gui from the terminal it was not closing when I clicked to close the gui,if I add root.destrpy() to the end of the script it will correctly destroy the gui if I have only worked on the TAB A of the gui but will not successfully close the gui if I have used the TAB B of the gui.
Code
print('\n'*2)
import tkinter.filedialog
import os
import re
import tkinter as tk
from tkinter import ttk
import matplotlib
matplotlib.use("TkAgg") # this is the backend of matplotlib
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.figure import Figure
import matplotlib.animation as animation
from matplotlib import style
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import easygui
from matplotlib.legend_handler import HandlerLine2D
from scipy.stats import linregress
pd.set_option("display.max_rows", None, "display.max_columns", None)
#=====================================================================
# ROOT FIGURE FOR GUI
#=====================================================================
root = tk.Tk()
root.title("Tab Widget")
root.geometry("600x450")
tabControl = ttk.Notebook(root)
tab1 = ttk.Frame(tabControl)
tab2 = ttk.Frame(tabControl)
tab3 = ttk.Frame(tabControl)
tab4 = ttk.Frame(tabControl)
tabControl.add(tab1, text ='Circle Cal')
tabControl.add(tab2, text ='OPW')
tabControl.add(tab3, text ='C')
tabControl.add(tab4, text ='D')
tk.Grid.rowconfigure(root, 0, weight=1)
tk.Grid.columnconfigure(root, 0, weight=1)
tabControl.grid(column=0, row=0, sticky=tk.E+tk.W+tk.N+tk.S)
#=====================================================================
# TAB A
#=====================================================================
#MAKE A FIGURE OBJECT
my_figure1 = Figure(figsize = (4, 4), dpi = 100)
#MAKE A FRAME WIDGET
frame1 = tk.Frame(tab1, bd=2, relief=tk.GROOVE)
frame1.pack(side=tk.LEFT, anchor=tk.N, fill=tk.BOTH, expand=True)
#create another frame(frame2)
frame2 = tk.Frame(tab1, bd=2, relief=tk.GROOVE)
frame2.pack(side=tk.RIGHT)
#MAKE A CANVAS OBJECT
my_canvas1 = FigureCanvasTkAgg(my_figure1, master = frame1) # creating the Tkinter canvas containing the Matplotlib figure
# TURN THE CANVAS OBJECT INTO A CANVAS WIDGET
my_canvas1.get_tk_widget().pack(side = tkinter.TOP, fill = tkinter.BOTH, expand = 1) # placing the canvas on the Tkinter window
my_canvas1.draw()
def plotData():
#my_figure1.clear()
file = easygui.fileopenbox(msg=None, title=None, default="/Users/.../Desktop/tk_gui_grid/", filetypes = None, multiple = False)
print('\n', "This is the selected file:", file, '\n')
# load data as a pandas dataframe
df = pd.read_csv(file, sep='\t', lineterminator='\n')
# make a smaller array by using the loc
df = df.loc[:,['Accum', 'EdgeThr','NumberOfBlobs']]
blob0 = []
blob1 = []
blob2 = []
blob0 = df[df['NumberOfBlobs'] == 0][['Accum', 'EdgeThr']]
blob1 = df[df['NumberOfBlobs'] == 1][['Accum', 'EdgeThr']]
blob2 = df[df['NumberOfBlobs'] == 2][['Accum', 'EdgeThr']]
blob0 = blob0.values.tolist()
blob1 = blob1.values.tolist()
blob2 = blob2.values.tolist()
print('blob2: ',blob2, '\n'*3)
fontTitle = {'family': 'arial',
'color': 'darkred',
'weight': 'normal',
'size': 16,
}
fontAxisLabels = {'family': 'helvetica',
'color': 'darkblue',
'weight': 'normal',
'size': 16,
}
if len(blob0)>0:
blob0_acc, blob0_et = map(list, zip(*blob0))
if len(blob1)>0:
blob1_acc, blob1_et = map(list, zip(*blob1))
if len(blob2)>0:
blob2_acc, blob2_et = map(list, zip(*blob2))
# MAKE INSTANCE OF FIGURE OBJECT AND RETURN IT WITH SUBPLOT ADDED
plot1 = my_figure1.add_subplot(111) # adding the subplot
if len(blob0)>0:
plot1.plot(blob0_et, blob0_acc, "s", color="blue", markersize=10, label = '0')
if len(blob1)>0:
plot1.plot(blob1_et, blob1_acc, "s", color="red", markersize=10, label = '1')
if len(blob2)>0:
plot1.plot(blob2_et, blob2_acc, "s", color="green", markersize=10, label = '2')
# plotting the graph
plot1.set_title ("Circle Calibration,Number of drops\n Accumulator vs Edge Threshold", fontname='arial', color=('black'),fontdict = fontTitle,fontsize = 10)
plot1.set_ylabel("Accumulator", fontdict = fontAxisLabels, fontsize = 12)
plot1.set_xlabel("Edge Threshold", fontdict = fontAxisLabels, fontsize = 12)
plot1.axis([0,250,0,50])
plot1.legend(loc = "upper right")
my_canvas1.draw()
def clearPlot():
my_figure1.clear()
my_canvas1.draw_idle()
# MAKE BUTTON TO PLOT GRAPH
button1 = tk.Button(frame2, text = "Plot", command = plotData, relief = tk.GROOVE, padx =20, pady =20 )
button1.pack(side="right")
# MAKE BUTTON TO CLEAR PLOT
button2 = tk.Button(frame2, text = "Clear", command = clearPlot, relief = tk.GROOVE, padx =20, pady =20 )
button2.pack(side="right")
#=====================================================================
# TAB B
#=====================================================================
#MAKE A FIGURE OBJECT
my_figure2 = Figure(figsize = (6, 6), dpi = 100)
#MAKE A FRAME WIDGET
frame1 = tk.Frame(tab2, bd=2, relief=tk.GROOVE)
frame1.pack(side=tk.LEFT, anchor=tk.N, fill=tk.BOTH, expand=True)
frame2 = tk.Frame(tab2, bd=2, relief=tk.GROOVE)
frame2.pack(side=tk.RIGHT)
#MAKE A CANVAS OBJECT
my_canvas2 = FigureCanvasTkAgg(my_figure2, master = frame1) # creating the Tkinter canvas containing the Matplotlib figure
# TURN THE CANVAS OBJECT INTO A CANVAS WIDGET
my_canvas2.get_tk_widget().pack() # placing the canvas on the Tkinter window
my_canvas2.draw()
def rsquared(x, y):
""" Return R^2 where x and y are array-like."""
slope, intercept, r_value, p_value, std_err = linregress(x, y)
return r_value**2
def plotOPWData():
fileOPW = easygui.fileopenbox(msg=None, title=None, default="/Users/.../Desktop/tk_gui_grid/", filetypes = None, multiple = False)
print('\n', "This is the selected file:", fileOPW, '\n')
# load data as a pandas dataframe
df = pd.read_csv(fileOPW, sep='\t', lineterminator='\r')
print('size of orig df:\n', df.shape)
#=====================================================================
# EXTRACT DATA FROM THE COMMENTS TAB
#=====================================================================
cols = ['rownumber', 'volts', 'wfm', 'sclk', 'image', 'segment']
exp = re.compile(r'Row\s'
r'(?P<rownumber>\d+).*\s' #(?P<name>...) stores the following part (\d+) under the name
# rownumber in the match object which we're going to use later on
r'(?P<volts>\d+\.\d+)V\s'
r'(?P<wfm>\w+)\sSclk\s'
r'(?P<sclk>\d+)ns\s'
r'(?P<image>\w+)\s'
r'(?P<segment>\d+)segs.*$')
df[cols] = df['Comments'].str.extract(exp, expand=True)
#create empty column for Pulse width data
dfLen = len(df)
pulse = [0]*dfLen
df['Pulse'] = pulse
#=====================================================================
# FILTERS
#=====================================================================
pw_filter_voltage = 17.0
filter_segment = 24
df[["Velocity_ms", "Volume_pl", "Trajectory_deg"]] = df[["Velocity_ms", "Volume_pl", "Trajectory_deg"]].apply(pd.to_numeric, errors = 'coerce')
df = df.dropna(subset=["Velocity_ms"])
df = df.reset_index(drop=True)
print('size of df:\n', df.shape)
#convert column data to numeric
df[[ "segment", "sclk", "rownumber", "volts"]] = df[["segment", "sclk", "rownumber", "volts"]].apply(pd.to_numeric)
#print('DEBUG --- Types of data: ', df.dtypes)
# Calculate the Pulse Width
df['Pulse'] = (df['segment'] * df['sclk']) / 1000
# selecting rows based on voltage condition
FIRST_filtered_df = df[df['volts'] == pw_filter_voltage]
#=====================================================================
# THIS WILL NEED TO BE LINKED TO BUTTONS IN THE GUI - WILL ALSO NEED TO HAVE DEFAULTS
pw_low_range = 1.4
pw_high_range = 3.0
range_filtered_df = FIRST_filtered_df [FIRST_filtered_df ['Pulse'] >= pw_low_range]
#=====================================================================
#Convert datarame columns to lists
PulseList = range_filtered_df['Pulse'].to_list()
VelList = range_filtered_df['Velocity_ms'].to_list()
VolList = range_filtered_df['Volume_pl'].to_list()
print('shape of range_filtered_df:\n', range_filtered_df.shape)
#=====================================================================
# Polynomial
#=====================================================================
p2 = np.polyfit(PulseList ,VelList ,2) # these are the x coefficients for the equation of the line
print('Coefficients for the polynomial p2:', p2,'\n')
# rounding down the polynomial values
np_array = np.array(p2)
np_round_to_tenths = np.around(np_array, 4)
P2round = list(np_round_to_tenths)
print('round_to_tenths:', P2round)
print(p2)
eq = ['x**2','x']
equation = ('y = ' + str(P2round[0])+eq[0] + ' + ' + str(P2round[1])+eq[1] + ' + ' +str(P2round[2]))
# ============================================================
# START PLOTTING
# ============================================================
plot2 = my_figure2.add_subplot(111) # adding the subplot
plot2.set_xlabel('Pulse Width $uS$')
plot2.set_ylabel('Velocity $(m/s)$ and Drop Volume $(pL)$')
#fig.clear()
image_used = range_filtered_df['image'][0]
print(' contents of df image:\n', image_used,'\n')
plot2.scatter(x=PulseList, y=VelList, marker='.', c='none', edgecolor='b', label = 'Velocity m/s')
plot2.scatter(x=PulseList, y=VolList, marker='.', c='none', edgecolor='r', label = 'Volume pL')
xp = np.linspace(pw_low_range, pw_high_range ,100) # this creates a linear vector, 100 values between -2 and 6
plot2.plot(xp,np.polyval(p2,xp),'m:', label = equation)
plot2.legend(loc='upper left')
plot2.set_xticks(np.arange(0, 3.2, 0.2))
plot2.set_yticks(np.arange(0, 8, 1))
plot2.set_facecolor('xkcd:light gray')
plot2.set_title('Drop Velocity and Volume vs Pulse Width ' +' Image:' + image_used, fontsize=10, fontweight='bold')
plot2.set_xlim([1, 3.2])
plot2.set_ylim([0, 8])
plot2.grid(True, linestyle='--')
plot2.legend(loc = "upper right")
print('func r-squared: ', rsquared(PulseList, VelList))
r2val = rsquared(PulseList, VelList)
r2val = round(r2val,4)
# place a text box in upper left in axes coords
plt.annotate('R^2: '+ str(r2val), xy=(0.05, 0.95), xycoords='axes fraction')
#Optimal sample clock
optimalSampleClock = (((-0.5)* P2round[1])/(P2round[0]))*100
optimalSampleClock = round(optimalSampleClock ,1)
print('optimal sample clock: ', optimalSampleClock)
plt.annotate('OPTsclk: '+ str(optimalSampleClock), xy=(0.05, 0.85), xycoords='axes fraction')
my_canvas2.draw()
# Add the toolbar
toolbar = NavigationToolbar2Tk(my_canvas2, frame1)
toolbar.update()
def clearPlotOPW():
my_figure2.clear()
my_canvas2.draw_idle()
# MAKE BUTTON TO PLOT GRAPH
button1_opw = tk.Button(frame2, text = "Plot", command = plotOPWData, relief = tk.GROOVE, padx =20, pady =20 )
button1_opw.pack(side="right")
# MAKE BUTTON TO CLEAR PLOT
button2_opw = tk.Button(frame2, text = "Clear", command = clearPlotOPW, relief = tk.GROOVE, padx =20, pady =20 )
button2_opw.pack(side="right")
#=====================================================================
# TAB C
#=====================================================================
#MAKE A FIGURE OBJECT
my_figure3 = Figure(figsize = (4, 4), dpi = 100)
#MAKE A FRAME WIDGET
frame1 = tk.Frame(tab3, bd=2, relief=tk.GROOVE)
frame1.pack(side=tk.LEFT, anchor=tk.N, fill=tk.BOTH, expand=True)
frame2 = tk.Frame(tab3, bd=2, relief=tk.GROOVE)
frame2.pack(side=tk.RIGHT)
#MAKE A CANVAS OBJECT
my_canvas3 = FigureCanvasTkAgg(my_figure3, master = frame1) # creating the Tkinter canvas containing the Matplotlib figure
# TURN THE CANVAS OBJECT INTO A CANVAS WIDGET
my_canvas3.get_tk_widget().pack() # placing the canvas on the Tkinter window
my_canvas3.draw()
def plotData():
plot1 = my_figure3.add_subplot(111) # adding the subplot
x = [1,2,3,4,5]
y = [1, 2, 4, 8,16]
plot1.plot(x, y, marker='o', c='r')
my_canvas3.draw()
def clearPlot():
my_figure3.clear()
my_canvas3.draw_idle()
# MAKE BUTTON TO PLOT GRAPH
button1 = tk.Button(frame2, text = "Plot", command = plotData, relief = tk.GROOVE, padx =20, pady =20 )
button1.pack(side="right")
# MAKE BUTTON TO CLEAR PLOT
button2 = tk.Button(frame2, text = "Clear", command = clearPlot, relief = tk.GROOVE, padx =20, pady =20 )
button2.pack(side="right")
#=====================================================================
# TAB D
#=====================================================================
#MAKE A FIGURE OBJECT
my_figure4 = Figure(figsize = (4, 4), dpi = 100)
#MAKE A FRAME WIDGET
frame1 = tk.Frame(tab4, bd=2, relief=tk.GROOVE)
frame1.pack(side=tk.LEFT, anchor=tk.N, fill=tk.BOTH, expand=True)
frame2 = tk.Frame(tab4, bd=2, relief=tk.GROOVE)
frame2.pack(side=tk.RIGHT)
#MAKE A CANVAS OBJECT
my_canvas4 = FigureCanvasTkAgg(my_figure4, master = frame1) # creating the Tkinter canvas containing the Matplotlib figure
# TURN THE CANVAS OBJECT INTO A CANVAS WIDGET
my_canvas4.get_tk_widget().pack() # placing the canvas on the Tkinter window
my_canvas4.draw()
def plotData():
plot1 = my_figure4.add_subplot(111) # adding the subplot
x = [1,2,3,4,5]
y = [1, 2, 3, 4, 5]
plot1.plot(x, y, marker='o', c='y')
my_canvas4.draw()
def clearPlot():
my_figure4.clear()
my_canvas4.draw_idle()
# MAKE BUTTON TO PLOT GRAPH
button1 = tk.Button(frame2, text = "Plot", command = plotData, relief = tk.GROOVE, padx =20, pady =20 )
button1.pack(side="right")
# MAKE BUTTON TO CLEAR PLOT
button2 = tk.Button(frame2, text = "Clear", command = clearPlot, relief = tk.GROOVE, padx =20, pady =20 )
button2.pack(side="right")
root.mainloop()
Terminal output from VS Code
/Users/me/opt/anaconda3/bin/python /Users/me/Desktop/tk_gui_grid/c_06.py
/Users/me/opt/anaconda3/bin/python /Users/me/Desktop/tk_gui_grid/c_06.py
Desired output
A gui I can see running each time I press run on VS code editor.
I found this How do I close a tkinter window? and a comment from Bryan Oakley which gave me what I needed. For the problem tab (TAB B) I added a destroy button with the command=quit which works fine. Will need to add that to all other tabs too.
# MAKE BUTTON TO DESTROY GUI
button4_opw = tk.Button(frame2, text = "Destroy", command = quit, relief = tk.GROOVE, padx =20, pady =20 )
button4_opw.pack(side="bottom")
I have been messing around with Tkinter and embedded graphs and from a tutorial I found on the net, I have been able to make the following snippet of code work perfectly:
from tkinter import *
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg # NavigationToolbar2TkAgg
from matplotlib.figure import Figure
root = Tk()
# Typical matplotlib code
f = Figure(figsize = (4,3), dpi = 100)
a = f.add_subplot(111)
a.plot([1,2,4,3,5,7,6,7,8,8,9,6,7,8,7,5,6,4,3,4,3,2,1])
canvas = FigureCanvasTkAgg(f, root)
canvas.draw()
canvas.get_tk_widget().pack()
canvas._tkcanvas.pack()
root.mainloop()
The problem is I have not been able to incorporate the idea into a program I have been working on (Collatz Conjecture algorithm). What I'm trying to do is to plot a graph of the iteration data points but the graph does not display, notwithstanding the fact that the relevant portions of code in my script and the example snippet are identical. See my code below:
#!/usr/local/bin/env python3
# -*- coding: utf-8 -*-
from tkinter import *
from tkinter import messagebox
root=Tk()
root.title("Collatz Conjecture")
import textwrap
# Matplotlib imports
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg # NavigationToolbar2TkAgg
from matplotlib.figure import Figure
# Functions
lst = []
def collatz(num):
lst.clear()
while num != 1:
lst.append(num)
if num % 2 == 0:
num = int(num / 2)
else:
num = int(3 * num + 1)
def main(event):
num = int(input.get())
collatz(num)
output1.delete(1.0, END)
output1.insert(END, lst)
output2.delete(1.0, END)
output2.insert(END, "Number of iterations: " + str(len(lst)))
lbl1 = Label(root, width = 20, text = "Type in number\n & press Enter")
lbl1.grid(row = 1, column = 0, sticky = W)
lbl2 = Label(root, width = 40, text = "THE COLLATZ CONJECTURE")
lbl2.grid(row = 4, column = 0)
input = Entry(root, width = 20, bg = "light grey")
input.grid(row = 1, padx = 6, sticky = E)
input.get()
input.bind("<Return>", main)
# Matplotlib Graph - typical code
f = Figure(figsize = (4,3), dpi = 100) # Create the figure
a = f.add_subplot(111) # Add subplot
a.plot(lst)
# Plot data in background
# Canvas
canvas = FigureCanvasTkAgg(f, root)
canvas.draw()
canvas.get_tk_widget().grid(row = 6, column = 0)
canvas._tkcanvas.grid(row = 6, column = 0)
# canvas = Canvas(root, width= 350, height= 350, bg = "white")
# canvas.grid(row = 6, column = 0, padx = (5,5), pady = (5,5))
bt1 = Button(root, width = 10, text = "About")
bt1.grid(row = 7, column = 0, pady = (5,7))
output1 = Text(root, wrap = WORD, width = 50, height = 7, bg = "light grey") # Note word wrap attribute
output1.grid(row = 3, column = 0, padx = (5,1), sticky = W)
output2 = Text(root, width = 50, height = 1, bg = "white")
output2.grid(row = 2, column = 0, sticky = W)
def about():
messagebox.showinfo("About", "The Collatz conjecture states that if you pick any positive whole number, and if its even, you divide it by two and if its odd, you multiply it by three and add one, and if you repeat this procedure often enough, the number that you started with will eventually reduce to one and if you play this game for long enough, your friends will eventually stop calling to see if you want to hang out ")
btn1 = Button(root, text = "About", command = about)
btn1.grid(row = 7, column = 0, pady = (5,7))
root.mainloop()
I'm pretty sure its an indent problem and that I'm going to be very embarrassed when someone points out my novice mistake but I've tried moving the code around in seeminlgly every possible way but without success.
Could someone please have a look at it and tell me not only where I went wrong but more importantly, WHY its wrong.
The issue is fundamental. Your tkinter window loop keeps refreshing the plot canvas so you don't get to see the data. What you could do instead is take the canvas out of your window loop and stick it in the main function.
Obviously there are other/better solutions but I hope this one highlights the issue you are facing.
# -*- coding: utf-8 -*-
from tkinter import *
from tkinter import messagebox
root=Tk()
root.title("Collatz Conjecture")
import textwrap
# Matplotlib imports
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg # NavigationToolbar2TkAgg
from matplotlib.figure import Figure
# Functions
lst = []
def collatz(num):
lst.clear()
while num != 1:
lst.append(num)
if num % 2 == 0:
num = int(num / 2)
else:
num = int(3 * num + 1)
def main(event):
num = int(inp_ut.get())
collatz(num)
output1.delete(1.0, END)
output1.insert(END, lst)
output2.delete(1.0, END)
output2.insert(END, "Number of iterations: " + str(len(lst)))
# Generate the data and populate the canvas once.
f = Figure(figsize = (4,3), dpi = 100) # Create the figure
a = f.add_subplot(111) # Add subplot
a.plot(lst)
canvas = FigureCanvasTkAgg(f, root)
canvas.draw()
canvas.get_tk_widget().grid(row = 6, column = 0)
canvas._tkcanvas.grid(row = 6, column = 0)
lbl1 = Label(root, width = 20, text = "Type in number\n & press Enter")
lbl1.grid(row = 1, column = 0, sticky = W)
lbl2 = Label(root, width = 40, text = "THE COLLATZ CONJECTURE")
lbl2.grid(row = 4, column = 0)
inp_ut = Entry(root, width = 20, bg = "light grey")
inp_ut.grid(row = 1, padx = 6, sticky = E)
inp_ut.get()
inp_ut.bind("<Return>", main)
# Canvas
# canvas = Canvas(root, width= 350, height= 350, bg = "white")
# canvas.grid(row = 6, column = 0, padx = (5,5), pady = (5,5))
bt1 = Button(root, width = 10, text = "About")
bt1.grid(row = 7, column = 0, pady = (5,7))
output1 = Text(root, wrap = WORD, width = 50, height = 7, bg = "light grey") # Note word wrap attribute
output1.grid(row = 3, column = 0, padx = (5,1), sticky = W)
output2 = Text(root, width = 50, height = 1, bg = "white")
output2.grid(row = 2, column = 0, sticky = W)
def about():
messagebox.showinfo("About", "The Collatz conjecture states that if you pick any positive whole number, and if its even, you divide it by two and if its odd, you multiply it by three and add one, and if you repeat this procedure often enough, the number that you started with will eventually reduce to one and if you play this game for long enough, your friends will eventually stop calling to see if you want to hang out ")
btn1 = Button(root, text = "About", command = about)
btn1.grid(row = 7, column = 0, pady = (5,7))
root.mainloop()
This post is related to my previous question.Updating Label and Live Graph dynamically using Arduino Data in Tkinter My graph is embedded on Tkinter. I was using the same code but I realized that while my live graph is updating dynamically from the serial data coming from the Arduino, the old data points just keeps on adding. I want to see the last 50 data points to be embedded in the live graph and to delete the old data point. I don't know how to manipulate the code to do exactly what I want to achieve. Any suggestions would be appreciated
Here's the code:
#from tkinter import *
import tkinter as tk # proper way to import tkinter
import serial
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import matplotlib.animation as animation
from matplotlib import style
style.use("ggplot")
import threading
class Dee(tk.Frame):
def __init__(self, master=None, title='', ylabel='', label='', color='c', ylim=1, **kwargs):
tk.Frame.__init__(self, master, **kwargs)
self.data = []
fig = Figure(figsize = (7,6))
self.plot = fig.add_subplot(111)
self.plot.set_title(title)
self.plot.set_ylabel(ylabel)
self.plot.set_ylim(0, ylim)
self.line, = self.plot.plot([], [], color, marker = 'o',label = label)
self.plot.legend(loc='upper left')
label = tk.Label(self, text = ylabel, font = "Times 22 bold")
label.grid(row = 0, column = 3)
button_1 = tk.Button(self, text = "Back To Homepage", command = F1.tkraise)
button_1.grid(row = 1, column = 2)
label_1 = tk.Label(self, text = "Current Value: ", font = "Verdana 10 bold")
label_1.grid(row = 2, column = 2)
self.label_data = tk.Label(self, font = "Verdana 10")
self.label_data.grid(row = 2, column = 3)
canvas = FigureCanvasTkAgg(fig, master=self)
canvas.get_tk_widget().grid(row = 3, column = 3)
ani = animation.FuncAnimation(fig, self.update_graph, interval = 1000, blit = False)
canvas.draw()
def update_graph(self, i):
if self.data:
self.line.set_data(range(len(self.data)), self.data)
self.plot.set_xlim(0, len(self.data))
def set(self, value):
self.data.append(value)
self.label_data.config(text=value)
my_window = tk.Tk()
my_window.title("Graphical User Interface Demo#1")
my_window.geometry("720x720")
F1 = tk.Frame(my_window)
F2 = Dee(my_window, title='Temperature Graph', ylabel='Temperature', color='c', label='Degrees C', ylim=40)
F3 = Dee(my_window, title='Humidity Graph', ylabel='Humidity', color='g', label='Percentage %', ylim=100)
F4 = Dee(my_window, title='Solved Water Graph', ylabel='Water Volume', color='b', label='mL', ylim=55)
#For Frame One
label_1 = tk.Label(F1, text = "Homepage of GUI", font = "Times 22 bold")
label_1.grid(row = 0, column = 3)
button_1 = tk.Button(F1, text = "Page of Humidity", bd = 8, command = F2.tkraise)
button_1.grid(row = 1, column = 2)
button_2 = tk.Button(F1, text = "Page of Temperature", bd = 8, command = F3.tkraise)
button_2.grid(row = 1, column = 3)
button_3 = tk.Button(F1, text = "Page of Water", bd = 8, command = F4.tkraise)
button_3.grid(row = 1, column = 4)
for frame in(F1, F2, F3, F4):
frame.grid(row = 0, column = 0, sticky = "NSEW")
F1.tkraise()
def get_data():
#Initialization of Serial Comm
ser = serial.Serial('COM3', 9600)
while True:
pulldata = ser.readline().decode('ascii')
get_data = pulldata.split(',')
F2.set(int(get_data[0]))
F3.set(int(get_data[1]))
F4.set(int(get_data[2]))
print(pulldata)
# start the thread that will poll the arduino
t = threading.Thread(target=get_data)
t.daemon = True
t.start()
my_window.mainloop()
To select only the last n data from an array use
data[-n:]
To let a plot autoscale use
ax.autoscale()
I have the following code:
from Tkinter import *
master = Tk()
center(master, 300, 200)
#Label(text = 'Clients').grid(row = 0, column = 1)
lb = Listbox(master, selectmode = BROWSE)
sb = Scrollbar(master)
sb.grid(row = 0, column = 0, sticky =NS, rowspan = 1)
lb.grid(row = 0, column = 1)
sb['command'] = lb.yview
lb['yscrollcommand'] = sb.set
Label(master, text = "AAAAA").grid(row = 0, column = 2)
Label(master, text = "BBBBB").grid(row = 1, column = 3)
mainloop()
Which creates this window:
I know I can use sticky = N to make AAAAA cling to the top of the cell and be at the top of the window.
But my question is: How do I make it so that I can put multiple labels next to my listbox widget in a sort of grid of their own? Can I use .grid for this? Or do I have to use .place?
Or am I going about this entirely wrong?