无法覆盖标签Tkinter
问题描述:
get_recs
由start
按钮触发。 get_recs
中的循环首先删除所有现有标签(但始终失败),然后创建标签,写入标签,然后将其添加到网格中。然而,每次按下start
时,现有标签都不会被销毁,而是会创建新标签而不是被替换。我只能假设这意味着每次执行循环时都会创建单独的标签,这可以解释为什么它们永远不会被销毁,但我不明白为什么。以下是代码:无法覆盖标签Tkinter
import pandas as pd
import numpy as np
from tkinter import *
from tkinter.filedialog import askopenfilename
from tkinter.messagebox import showwarning, showinfo
movies = pd.read_csv('C:/Users/Admin/Python Programs/ml-latest-small/movies.csv')
ratings = pd.read_csv('C:/Users/Admin/Python Programs/ml-latest-small/ratings.csv')
ratings.drop(['timestamp'], axis=1, inplace= True)
class App(Frame):
def replace_name(x):
return movies[movies['movieId']==x].title.values[0]
ratings.movieId = ratings.movieId.map(replace_name)
M = ratings.pivot_table(index=['userId'], columns=['movieId'], values='rating')
def pearsons(s1, s2):
s1_c = s1 - s1.mean()
s2_c = s2 - s2.mean()
return np.sum(s1_c * s2_c)/np.sqrt(np.sum(s1_c ** 2) * np.sum(s2_c ** 2))
def get_recs(self):
movie_name = self.mn.get()
num_recs_str = self.nr.get()
num_recs = int(num_recs_str)
reviews = []
for title in App.M.columns:
if title==movie_name:
continue
cor = App.pearsons(App.M[movie_name], App.M[title])
if np.isnan(cor):
continue
else:
reviews.append((title, cor))
reviews.sort(key=lambda tup: tup[1], reverse=True)
Frame3= Frame(root, bg= 'red')
Frame3.grid()
#for i in range(num_recs):
#exec("Label%d=Label(Frame3,text='', fg = 'blue')\nLabel%d.grid()" % (i,i))
#var_exists = 'Label0' in locals() or 'Label0' in globals()
for i in range(num_recs):
try:
exec("Label%d.destroy()" % (i))
except (NameError):
pass
exec("Label%d=Label(Frame3,text='', fg = 'blue')\n" % (i))
exec("Label%d.config(text=%s)" % (i,reviews[i]))
exec("Label%d.grid()" % (i))
print ("success")
#exec("print (%d)" % (i))
#for x in reviews:
#self.label3.config(text= "\n" + str(reviews[:num_recs]))
#self.label3.config(text=reviews[:num_recs])
return reviews[:num_recs]
def __init__(self, master):
Frame.__init__(self, master)
Frame1 = Frame(master)
Frame1.grid()
Frame2 = Frame(master)
Frame2.grid()
self.filename = None
label1=Label(Frame1, text="Movie: ").grid(row=0, sticky=W)
label2=Label(Frame1, text="Recommendations: ").grid(row=1, sticky=W)
#self.label3=Label(master, text = "", font = 'Purisa', fg='blue')
#self.label3.grid(row = 3)
self.mn = Entry(Frame1)
self.mn.grid(row = 0, column = 1, sticky=W)
#self.mn.delete(0, END)
self.mn.insert(0, "Enter Movie Name")
self.nr = Entry(Frame1)
self.nr.grid(row = 1, column = 1, sticky=W)
#self.nr.delete(0, END)
self.nr.insert(0, "Enter Number of Recommendations")
button1 = Button(Frame2, text="Start", command=self.get_recs)
button2 = Button(Frame2, text="Exit", command=master.destroy)
button1.grid(row = 0, column = 0, padx= 5, pady = 5, sticky =W)
button2.grid(row = 0, column = 1, padx = 5, pady =5, sticky =W)
self.grid()
root = Tk()
root.title("Recommender")
root.geometry("500x500")
app = App(root)
root.mainloop()
答
由于您的标签是在本地创建的,因此您的代码会抛出NameError。在第二次点击时,您无法找到它们,并且因为您只是在区块外部,所以您什么也看不到。
一种方法是,您可以创建标签,作为类变量
for i in range(num_recs):
try:
exec("self.Label%d.destroy()" % (i))
except NameError:
print("A NameError has occured")
except AttributeError:
exec("self.Label%d=Label(Frame3,text='', fg = 'blue')\n" % (i))
exec("self.Label%d.config(text=%s)" % (i,reviews[i]))
exec("self.Label%d.grid()" % (i))
代替这种方法,你可以把你所有的标签到一个列表,然后检查是否说标签列表与否。这是,恕我直言,更好的方法。
#a list created in global scope to store all labels
labels = []
def get_recs(self):
....
for i in range(num_recs):
try:
for label in labels:
if label["text"] == reviews[i]:
label.destroy() #destroy the matching label
labels.remove(label) #remove it from labels list
except (NameError):
#Please don't just pass Exceptions. They are there for a reason
print("A NameError has occured")
labels.append(Label(Frame3,text='', fg = 'blue'))
labels[-1].config(text=reviews[i])
labels[-1].grid()
不要使用exec!这可能很方便,但不要。 – abccd
而且你基本上总是在该循环中创建的每个标签都有一个NameError,但你不知道,因为你通过了它 – abccd