使用TkInter设置和检索数据

时间:2016-03-02 19:30:21

标签: python-2.7 tkinter python-decorators

我刚遇到一些令我难过的奇怪行为。我正在为一些内部数据处理编写一个简单的小GUI。我想允许用户在几种不同的数据处理模式之间切换,并输入一些参数,这些参数定义了如何为每种模式处理数据。问题是当用户输入新参数时,应用程序会忽略切换模式的请求。

以下代码会复制此问题。我为大小道歉,这是复制问题的最短代码。

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”按钮,然后“打印”打印:

  

Yay

2)按“b”按钮,然后“打印”打印:

  

3)在输入字段中输入“Zep Rocks”,然后按“应用”

4)现在按“打印”会产生

  

Zep Rocks

5)按'a'然后'print'应该产生

  

而是收益

  

Zep Rocks

这可能是真的,但现在并不需要。这是怎么回事?

编辑:我有一些新信息。 python 2.7中的Tk.Frame不是一个新式的类。它与描述符不友好,因此它不是将'='解释为使用foo.innerdata的__set__方法的请求,而只是将self.e.get()的结果赋给innerdata。

ARGLEBARGLE !!!

仍然是一个悬而未决的问题:我怎样才能以干净的方式做到我想做的事情?

1 个答案:

答案 0 :(得分: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()