2016-03-02 35 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()