我有一个 GUI,允许用户使用形状创建点集(例如,以 X、Y 为中心、直径为 D 的圆,有 N 个点,其中 X、Y、D 和 N 是使用输入框输入的值) .
从生成的点集中,我进入 TreeView 并绘制点。然后,用户可以选择 TreeView 条目来突出显示绘图上的这些点。
数据图很好(我用空白数据集初始化散点图,然后每次用户生成输入时向其中添加数据)。我遇到的问题是用户是否删除数据(使用 GUI 中的删除按钮)。存储数据的字典 (self.patterns) 正确更新,但由于某种原因,数据没有从图中删除。
我假设使用清除数据集
self.scat = self.ptrnFig.scatter([], [], c="b", marker="o", s=40)
在plotAllPtrns()函数中会给我一个空的散点图(就像我初始化绘图时一样),我可以将数据集中的剩余点重新添加到散点图中,但这似乎不起作用.
我还尝试添加
self.scat.remove()
行位于plotAllPtrns() 的开头,但随后仅绘制最后一组用户定义的点,而不是表中剩余的所有点。
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')
for i in range(9):
self.rowconfigure(i, weight=1)
self.columnconfigure(i, weight=1)
self.mydict = {}
self.makeTable()
self.initializePlot()
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, text=self.labText[i])
self.label.grid(column=j, row=k + 8, sticky='SW')
self.Labels.append(self.label)
self.entry = tk.Entry(self)
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, text='Add Entry', command=self.addEntry)
self.addBtn.grid(column=self.xGrid + 1, row=self.yGrid + 9, sticky='NSEW')
self.delBtn = tk.Button(self, text='Delete Entry', command=self.delEntry)
self.delBtn.grid(column=self.xGrid, row=self.yGrid + 9, sticky='NSEW')
def makeTable(self):
tab_header = ['Pattern #', 'Description']
self.tree = ttk.Treeview(self, columns=tab_header, height=5, show="headings")
self.tree.grid(column=0, row=0, columnspan=2, rowspan=5, sticky='NSEW')
self.tree.heading(tab_header[0], text=tab_header[0].title())
self.tree.heading(tab_header[1], text=tab_header[1].title())
self.tree.insert('', 'end', values=("", "(new)"))
self.tree.bind("<ButtonRelease-1>", self.getPtrnTable)
self.counter = 1
def getPtrnTable(self, event):
self.item = self.tree.identify_row(event.y)
try:
self.patNum = self.tree.item(self.item, 'values')[0]
except IndexError:
self.patNum = ''
self.patternPlot()
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())]
patKey = 'pattern_' + str(self.counter - 1)
self.mydict[patKey] = newEntry
if(check == True):
self.points = np.array(newEntry, ndmin=2)
else:
self.points = np.vstack((self.points, newEntry))
self.counter += 1
self.scat.set_offsets(self.points)
self.patNum = ""
print("mydict: ", self.mydict)
self.patternPlot()
def delEntry(self):
treeCnt = len(self.tree.get_children())
patKey = 'pattern_' + str(int(self.patNum) - 1)
del self.mydict[patKey]
items = self.tree.get_children()
for i in range(int(self.patNum), treeCnt - 1):
old_key = 'pattern_' + str(i)
new_key = 'pattern_' + str(i - 1)
self.mydict[new_key] = self.mydict.pop(old_key)
self.tree.set(items[i], 'Description', self.tree.item(items[i + 1], 'values')[1])
self.tree.delete(items[-1])
self.patNum = ""
self.patternPlot()
print("mydict: ", self.mydict)
def initializePlot(self):
self.fig = Figure(figsize=(1, 1), dpi=100)
self.ptrnFig = self.fig.add_subplot(111)
self.ptrnFig.axis([-5, 5, -5, 5])
self.ptrnFig.spines['left'].set_position('zero')
self.ptrnFig.spines['bottom'].set_position('zero')
self.ptrnFig.grid(True)
self.canvas = FigureCanvasTkAgg(self.fig, self)
self.canvas.draw()
self.canvas.get_tk_widget().grid(column=2, row=0, columnspan=6, rowspan=5, sticky='NSEW')
self.scat = self.ptrnFig.scatter([], [], c="b", marker="o")
self.scat2 = self.ptrnFig.scatter([], [], c="#ff5733", marker="o") # Orange Color
def plotAllPtrns(self):
self.scat = self.ptrnFig.scatter([], [], c="b", marker="o", s=40)
self.scat2.remove()
self.scat2 = self.ptrnFig.scatter([], [], c="#ff5733", marker="o") # Orange Color
for k, v in self.mydict.items():
x = self.mydict[k][0]
y = self.mydict[k][1]
bolt = np.array([x, y], ndmin=2)
self.scat.set_offsets(bolt)
self.canvas.draw_idle()
def patternPlot(self):
# All data deleted - reinitialize plot
if(len(self.tree.get_children()) == 1):
plt.close(self.fig)
self.initializePtrnPlot()
# No specific entry selected - plot everything
elif(self.patNum == ""):
self.plotAllPtrns()
# Specific entry chosen - highlight selected entry
else:
self.scat2.remove()
self.scat2 = self.ptrnFig.scatter([], [], c="#ff5733", marker="o") # Orange Color
patKey = 'pattern_' + str(int(self.patNum) - 1)
x = self.mydict[patKey][0]
y = self.mydict[patKey][1]
bolt = np.array([x, y], ndmin=2)
self.scat2.set_offsets(bolt)
self.canvas.draw_idle()
def main():
MainGUI().mainloop()
if __name__ == '__main__':
main()
我在这里缺少什么?我觉得在删除数据集后,清除分散并重新填充它(就像我只是添加数据一样)应该可以工作。
更新: 根据要求,我添加了代码的最小工作版本。它不是像上面描述的那样创建模式,而是只是单点。根据需要添加点,在表中单击它们以在绘图上突出显示它们,然后使用删除将它们从表和存储它们的字典中删除。删除点时,绘图不会更新,我可以不明白为什么。
谢谢。
最佳答案
我将简单地按原样提供以下代码,这似乎可以解决问题。但请注意......在某些情况下,它会产生其他错误,因为 self.patNum
的定义和使用不一致。我也无法修复这些问题。
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')
for i in range(9):
self.rowconfigure(i, weight=1)
self.columnconfigure(i, weight=1)
self.mydict = {}
self.patNum = ''
self.makeTable()
self.initializePlot()
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, text=self.labText[i])
self.label.grid(column=j, row=k + 8, sticky='SW')
self.Labels.append(self.label)
self.entry = tk.Entry(self)
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, text='Add Entry', command=self.addEntry)
self.addBtn.grid(column=self.xGrid + 1, row=self.yGrid + 9, sticky='NSEW')
self.delBtn = tk.Button(self, text='Delete Entry', command=self.delEntry)
self.delBtn.grid(column=self.xGrid, row=self.yGrid + 9, sticky='NSEW')
def makeTable(self):
tab_header = ['Pattern #', 'Description']
self.tree = ttk.Treeview(self, columns=tab_header, height=5, show="headings")
self.tree.grid(column=0, row=0, columnspan=2, rowspan=5, sticky='NSEW')
self.tree.heading(tab_header[0], text=tab_header[0].title())
self.tree.heading(tab_header[1], text=tab_header[1].title())
self.tree.insert('', 'end', values=("", "(new)"))
self.tree.bind("<ButtonRelease-1>", self.getPtrnTable)
self.counter = 1
def getPtrnTable(self, event):
self.item = self.tree.identify_row(event.y)
try:
self.patNum = self.tree.item(self.item, 'values')[0]
except IndexError:
self.patNum = ''
self.patternPlot()
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())]
patKey = 'pattern_' + str(self.counter - 1)
self.mydict[patKey] = newEntry
if(check == True):
self.points = np.array(newEntry, ndmin=2)
else:
self.points = np.vstack((self.points, newEntry))
self.counter += 1
self.scat.set_offsets(self.points)
self.patNum = ""
print("mydict: ", self.mydict)
self.patternPlot()
def delEntry(self):
treeCnt = len(self.tree.get_children())
if self.patNum:
patKey = 'pattern_' + str(int(self.patNum) - 1)
del self.mydict[patKey]
items = self.tree.get_children()
for i in range(int(self.patNum), treeCnt - 1):
old_key = 'pattern_' + str(i)
new_key = 'pattern_' + str(i - 1)
self.mydict[new_key] = self.mydict.pop(old_key)
self.tree.set(items[i], 'Description', self.tree.item(items[i + 1], 'values')[1])
self.tree.delete(items[-1])
print("mydict: ", self.mydict)
self.plotAllPtrns()
def initializePlot(self):
self.fig = Figure(figsize=(1, 1), dpi=100)
self.ptrnFig = self.fig.add_subplot(111)
self.ptrnFig.axis([-5, 5, -5, 5])
self.ptrnFig.spines['left'].set_position('zero')
self.ptrnFig.spines['bottom'].set_position('zero')
self.ptrnFig.grid(True)
self.canvas = FigureCanvasTkAgg(self.fig, self)
self.canvas.draw()
self.canvas.get_tk_widget().grid(column=2, row=0, columnspan=6, rowspan=5, sticky='NSEW')
self.scat = self.ptrnFig.scatter([], [], c="b", marker="o")
self.scat2 = self.ptrnFig.scatter([], [], c="#ff5733", marker="o") # Orange Color
def plotAllPtrns(self):
print(self.mydict)
self.scat.remove()
self.scat = self.ptrnFig.scatter([], [], c="b", marker="o", s=40)
self.scat2.remove()
self.scat2 = self.ptrnFig.scatter([], [], c="#ff5733", marker="o") # Orange Color
xy = []
for k, v in self.mydict.items():
xy.append([self.mydict[k][0], self.mydict[k][1]])
if xy:
self.scat.set_offsets(xy)
self.canvas.draw_idle()
def patternPlot(self):
print(self.tree.get_children())
# All data deleted - reinitialize plot
if(len(self.tree.get_children()) == 1):
print("One Child")
# No specific entry selected - plot everything
elif(self.patNum == ""):
self.plotAllPtrns()
# Specific entry chosen - highlight selected entry
else:
self.scat2.remove()
self.scat2 = self.ptrnFig.scatter([], [], c="#ff5733", marker="o") # Orange Color
patKey = 'pattern_' + str(int(self.patNum) - 1)
x = self.mydict[patKey][0]
y = self.mydict[patKey][1]
bolt = np.array([x, y], ndmin=2)
self.scat2.set_offsets(bolt)
self.canvas.draw_idle()
def main():
MainGUI().mainloop()
if __name__ == '__main__':
main()
关于python - matplotlib:从数据集中删除数据时散点图不更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53612171/