2016-03-02 68 views
0

我剛碰到一些讓我難以理解的奇怪行爲。我正在爲一些內部數據處理編寫簡單的GUI。我想允許用戶在幾種不同的數據處理模式之間切換,並輸入一些參數來定義每種模式下數據的處理方式。問題是,當用戶輸入新參數時,應用程序將忽略切換模式的請求。使用TkInter設置和檢索數據

下面的代碼會重現此問題。我對這個大小表示歉意,這是複製問題的最短代碼。

import Tkinter as Tk 

class foo(Tk.Frame): 
    def __init__(self): 
     self.master = master =Tk.Tk() 
     Tk.Frame.__init__(self,self.master) #Bootstrap 

     #Here mode and parameters as key, value pairs 
     self.data = {'a':'Yay', 
        'b':'Boo' 
        } 

     self.tex = Tk.Text(master=master) 
     self.tex.grid(row=0,column=0,rowspan=3,columnspan=4) 

     self.e = Tk.Entry(master=master) 
     self.e.grid(row=3,column=0,columnspan=4) 

     self.sv =Tk.StringVar() 
     self.sv.set('a') 
     self.b1 = Tk.Radiobutton(master=master, 
           text = 'a', 
           indicatoron = 0, 
           variable = self.sv, 
           value = 'a') 

     self.b2 = Tk.Radiobutton(master=master, 
           text = 'b', 
           indicatoron = 0, 
           variable = self.sv, 
           value = 'b') 

     self.b3 = Tk.Button(master = master, 
          text='Apply',command=self.Apply_Func) 
     self.b4 = Tk.Button(master = master, 
          text='Print',command=self.Print_Func) 
     self.b1.grid(row=4,column=0) 
     self.b2.grid(row=4,column=1) 
     self.b3.grid(row=4,column=2) 
     self.b4.grid(row=4,column=3) 

    def Apply_Func(self): 
     self.innerdata = self.e.get() 

    def Print_Func(self): 
     self.tex.insert(Tk.END,str(self.innerdata)+'\n') 

    #This is how I'm retrieving the user selected parameters 
    @property  
    def innerdata(self): 
     return self.data[self.sv.get()] 

    #And how I'm setting the user defined parameters 
    @innerdata.setter 
    def innerdata(self,value): 
     self.data[self.sv.get()] = value  

if __name__ == "__main__":  
    app = foo() 
    app.mainloop() 

預期行爲:

1)按下按鈕 'A' 然後 '打印' 打印:

2)按下按鈕 'B',然後「打印'prints:

Boo

3)鍵入 '番岩石' 到輸入字段並按申請

4)按下 '打印' 現在產生

番岩石

5)按​​' '然後'打印'應該收益

Yay

但是相反產生

澤普岩石

這可能是真的,但不希望現在。這裏發生了什麼?

編輯:我有一些新的信息。 python 2.7中的Tk.Frame不是一種新風格的類。它與描述符不友好,所以不是將'='解釋爲使用foo.innerdata的__set__方法的請求,而是將self.e.get()的結果賦值給innerdata。

ARGLEBARGLE !!!

還有一個懸而未決的問題:我如何以乾淨的方式做到我想做的事?

回答

0

所以核心問題是Tk.Frame沒有從對象中繼承,所以它不是一個新式的python類。這意味着它不會像我試圖使用的描述符一樣。我找到的一個解決方案是將我的應用程序從對象中繼承。該解決我的問題

代碼如下:

import Tkinter as Tk 

class foo(object): 
    def __init__(self,master): 
     self.master = master #Bootstrap 
     self.mainloop = master.mainloop 

     self.data = {'a':{'value':7,'metavalue':False}, 
        'b':{'value':'Beeswax','metavalue':True} 
        } 

     self.tex = Tk.Text(master=master) 
     self.tex.grid(row=0,column=0,rowspan=3,columnspan=4) 

     self.e = Tk.Entry(master=master) 
     self.e.grid(row=3,column=0,columnspan=4) 

     self.sv =Tk.StringVar() 
     self.sv.set('a') 
     self.b1 = Tk.Radiobutton(master=master, 
           text = 'a', 
           indicatoron = 0, 
           variable = self.sv, 
           value = 'a') 

     self.b2 = Tk.Radiobutton(master=master, 
           text = 'b', 
           indicatoron = 0, 
           variable = self.sv, 
           value = 'b') 

     self.b3 = Tk.Button(master = master,text='Apply',command=self.Apply_Func) 
     self.b4 = Tk.Button(master = master,text='Print',command=self.Print_Func) 
     self.b1.grid(row=4,column=0) 
     self.b2.grid(row=4,column=1) 
     self.b3.grid(row=4,column=2) 
     self.b4.grid(row=4,column=3) 

    def Apply_Func(self): 
     self.innerdata = self.e.get() 

    def Print_Func(self): 
     self.tex.insert(Tk.END,str(self.innerdata)+'\n') 

    @property  
    def innerdata(self): 
     return self.data[self.sv.get()] 

    @innerdata.setter 
    def innerdata(self,value): 
     self.data[self.sv.get()] = value 


if __name__ == "__main__": 
    master = Tk.Tk()  
    app = foo(master) 
    app.mainloop()