2017-04-17 118 views
1

get_recsstart按鈕觸發。 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() 
+1

不要使用exec!這可能很方便,但不要。 – abccd

+0

而且你基本上總是在該循環中創建的每個標籤都有一個NameError,但你不知道,因爲你通過了它 – abccd

回答

1

由於您的標籤是在本地創建的,因此您的代碼會拋出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()