Reputation: 33
In this example you can input point coordinates which are then saved in a treeview and plotted. Simple enough. What I've found though is that I can "initialize" my plot to be formatted how I want, but as soon as I add the first point, the plot seems to "grow" and take up more of the tkinter window. I have no idea why this happens or how to control this so it maintains its original size. Thanks.
import tkinter as tk
from tkinter import ttk
import numpy as np
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib
from matplotlib.figure import Figure
matplotlib.use("TkAgg")
class MainGUI(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.title('Title')
self.geometry('750x500')
self.nb = ttk.Notebook(self)
self.nb.grid(row=0, column=0, columnspan=5, rowspan=4, sticky='NESW')
self.tab2 = ttk.Frame(self.nb)
self.nb.add(self.tab2, text='Tab2')
self.rowconfigure(0, weight=1)
self.columnconfigure(0, weight=1)
tab2_r = 8
tab2_c = 4
for i in range(tab2_r):
self.tab2.rowconfigure(i, weight=1)
for i in range(tab2_c):
self.tab2.columnconfigure(i, weight=1)
self.makeTable()
self.makePlot()
self.makeWidgets()
def makeWidgets(self):
self.Labels = []
self.Entries = []
self.labText = [('X Location:'), ('Y Location:')]
self.xGrid = 1
self.yGrid = int(np.ceil(len(self.labText) / self.xGrid))
i = 0
for j in range(0, self.xGrid + 1, 2):
for k in range(self.yGrid):
if(i == len(self.labText)):
break
else:
self.label = tk.Label(self.tab2, text=self.labText[i])
self.label.grid(column=j, row=k + 8, sticky='SW')
self.Labels.append(self.label)
self.entry = tk.Entry(self.tab2)
self.entry.insert(0, '0.0000')
self.entry.grid(column=j + 1, row=k + 8, sticky='NS')
self.Entries.append(self.entry)
i += 1
self.addBtn = tk.Button(self.tab2, text='Add Entry', command=self.addEntry)
self.addBtn.grid(column=self.xGrid + 1, row=self.yGrid + 9, sticky='NSEW')
def makeTable(self):
tab_header = ['Pattern #', 'Description']
self.tree = ttk.Treeview(self.tab2, columns=tab_header, height=5, show="headings")
vsb = ttk.Scrollbar(self.tab2, orient="vertical", command=self.tree.yview)
self.tree.configure(yscrollcommand=vsb.set)
self.tree.grid(column=0, row=0, columnspan=2, rowspan=5, sticky='NSEW')
vsb.grid(column=1, row=0, rowspan=5, sticky='ENS')
self.tree.heading(tab_header[0], text=tab_header[0].title())
self.tree.column(tab_header[0], width=30, anchor='center')
self.tree.heading(tab_header[1], text=tab_header[1].title())
self.tree.column(tab_header[1], width=170, anchor='center')
self.tree.insert('', 'end', values=("", "(new)"))
self.counter = 1
def addEntry(self):
check = (len(self.tree.get_children()) == 1)
self.description = "Location: " + self.Entries[0].get() + ", " + self.Entries[1].get()
self.tree.insert('', 'end', values=(self.counter, self.description))
newEntry = [float(self.Entries[0].get()), float(self.Entries[1].get())]
if(check == True):
self.points = newEntry
else:
self.points = np.vstack((self.points, newEntry))
self.counter += 1
self.plotstuff()
def makePlot(self):
self.fig = Figure(figsize=(1, 1), dpi=100)
self.ptrnFig = self.fig.add_subplot(111)
self.ptrnFig.plot([1], [1])
self.ptrnFig.axis([-1, 1, -1, 1])
self.ptrnFig.spines['left'].set_position('zero')
self.ptrnFig.spines['bottom'].set_position('zero')
self.ptrnFig.grid(True)
self.canvas = FigureCanvasTkAgg(self.fig, self.tab2)
self.canvas.draw()
self.canvas.get_tk_widget().grid(column=2, row=0, columnspan=2, rowspan=5, sticky='NSEW')
def plotstuff(self):
self.ptrnFig.cla()
if(np.ndim(self.points) == 1):
x = self.points[0]
y = self.points[1]
else:
x = self.points[:, 0]
y = self.points[:, 1]
self.ptrnFig.grid(True)
self.ptrnFig.axis('equal')
self.ptrnFig.scatter(x, y, c="b", marker="o")
self.canvas = FigureCanvasTkAgg(self.fig, self.tab2)
self.canvas.draw()
self.canvas.get_tk_widget().grid(column=2, row=0, columnspan=2, rowspan=5, sticky='NSEW')
def main():
MainGUI().mainloop()
if __name__ == '__main__':
main()
Upvotes: 0
Views: 2106
Reputation: 40747
I cannot really say why the plot area grows. What I can tell you, though, is that you are using the wrong strategy. You are creating a new figure and new canvas everytime you're adding a new point, which is wasting a lot of energy and causing you your problems. Instead, you should create an empty plot, with an empty artist, and add new points to this artist everytime the button is clicked.
Consider the code (the modifications I made are mostly in makePlot()
and plotstuff()
):
import tkinter as tk
from tkinter import ttk
import numpy as np
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib
from matplotlib.figure import Figure
matplotlib.use("TkAgg")
class MainGUI(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.title('Title')
self.geometry('750x500')
self.nb = ttk.Notebook(self)
self.nb.grid(row=0, column=0, columnspan=5, rowspan=4, sticky='NESW')
self.tab2 = ttk.Frame(self.nb)
self.nb.add(self.tab2, text='Tab2')
self.rowconfigure(0, weight=1)
self.columnconfigure(0, weight=1)
tab2_r = 8
tab2_c = 4
for i in range(tab2_r):
self.tab2.rowconfigure(i, weight=1)
for i in range(tab2_c):
self.tab2.columnconfigure(i, weight=1)
self.makeTable()
self.makePlot()
self.makeWidgets()
def makeWidgets(self):
self.Labels = []
self.Entries = []
self.labText = [('X Location:'), ('Y Location:')]
self.xGrid = 1
self.yGrid = int(np.ceil(len(self.labText) / self.xGrid))
i = 0
for j in range(0, self.xGrid + 1, 2):
for k in range(self.yGrid):
if(i == len(self.labText)):
break
else:
self.label = tk.Label(self.tab2, text=self.labText[i])
self.label.grid(column=j, row=k + 8, sticky='SW')
self.Labels.append(self.label)
self.entry = tk.Entry(self.tab2)
self.entry.insert(0, '0.0000')
self.entry.grid(column=j + 1, row=k + 8, sticky='NS')
self.Entries.append(self.entry)
i += 1
self.addBtn = tk.Button(self.tab2, text='Add Entry', command=self.addEntry)
self.addBtn.grid(column=self.xGrid + 1, row=self.yGrid + 9, sticky='NSEW')
def makeTable(self):
tab_header = ['Pattern #', 'Description']
self.tree = ttk.Treeview(self.tab2, columns=tab_header, height=5, show="headings")
vsb = ttk.Scrollbar(self.tab2, orient="vertical", command=self.tree.yview)
self.tree.configure(yscrollcommand=vsb.set)
self.tree.grid(column=0, row=0, columnspan=2, rowspan=5, sticky='NSEW')
vsb.grid(column=1, row=0, rowspan=5, sticky='ENS')
self.tree.heading(tab_header[0], text=tab_header[0].title())
self.tree.column(tab_header[0], width=30, anchor='center')
self.tree.heading(tab_header[1], text=tab_header[1].title())
self.tree.column(tab_header[1], width=170, anchor='center')
self.tree.insert('', 'end', values=("", "(new)"))
self.counter = 1
def addEntry(self):
check = (len(self.tree.get_children()) == 1)
self.description = "Location: " + self.Entries[0].get() + ", " + self.Entries[1].get()
self.tree.insert('', 'end', values=(self.counter, self.description))
newEntry = [float(self.Entries[0].get()), float(self.Entries[1].get())]
if(check == True):
self.points = np.array(newEntry, ndmin=2)
else:
self.points = np.vstack((self.points, newEntry))
self.counter += 1
self.plotstuff()
def makePlot(self):
self.fig = Figure(figsize=(1, 1), dpi=100)
self.ptrnFig = self.fig.add_subplot(111)
self.ptrnFig.axis([-1, 1, -1, 1])
self.ptrnFig.spines['left'].set_position('zero')
self.ptrnFig.spines['bottom'].set_position('zero')
self.ptrnFig.grid(True)
self.canvas = FigureCanvasTkAgg(self.fig, self.tab2)
self.canvas.draw()
self.canvas.get_tk_widget().grid(column=2, row=0, columnspan=2, rowspan=5, sticky='NSEW')
self.scat = self.ptrnFig.scatter([], [], c="b", marker="o")
def plotstuff(self):
self.scat.set_offsets(self.points)
# adjust the limits of the axes
xmin = min(self.points[:, 0])
xmax = max(self.points[:, 0])
ymin = min(self.points[:, 1])
ymax = max(self.points[:, 1])
self.ptrnFig.set_xlim(xmin - 0.1 * (xmax - xmin), xmax + 0.1 * (xmax - xmin))
self.ptrnFig.set_ylim(ymin - 0.1 * (ymax - ymin), ymax + 0.1 * (ymax - ymin))
self.canvas.draw_idle()
def main():
MainGUI().mainloop()
if __name__ == '__main__':
main()
Upvotes: 1