跟踪子类中定义的radiobutton值,并将其传递给Python中的父类

时间:2015-01-10 10:39:49

标签: python tkinter parent-child trace

我是Python和Tkinter的新手,所以无法弄清楚哪个可能是最简单的事情。有人请检查下面的代码并告诉我如何跟踪子类中定义的radiobutton返回的值并将其传递给父类。编译后我收到以下错误:

AttributeError: Toplevel instance has no attribute 'trace_fun'

我不确定为什么我收到此错误,因为我在子类体中定义了trace_fun。我已成功跟踪父类中的变量,但在尝试在子类中执行此操作时遇到上述错误。

from Tkinter import *

class Parent(Frame):
    classvar = 0

    def __init__(self):

        Frame.__init__(self)
        self.master.title("Parent WIndow")
        self.master.geometry("200x100")
        self.grid()

        self._button = Button(self, text="Create", width=10, command=self.new_window)
        self._button.grid(row=0, column=0, sticky=E+W)

    def new_window(self):
        self.new = Child()

class Child(Parent, Frame):

    def __init__(self):

        Parent.__init__(self)
        new = Frame.__init__(self)
        new = Toplevel(self)
        new.title("Child Window")
        new.grid()

        new._var = IntVar()
        new._var.set(0)
        new._var.trace("w", new.trace_fun)

        new._radioButton = Radiobutton(new, text = "Option 1", variable = new._var, value = 1)
        new._radioButton.grid(row=0, column=0, sticky=W, padx=10, pady=10)

        new._radioButton2 = Radiobutton(new, text = "Option 2", variable = new._var, value = 2)
        new._radioButton2.grid(row=1, column=0, sticky=W, padx=10, pady=10)

        new._button = Button(new, text = 'Ok', command=new.destroy)
        new._button.grid(row=2, column=0, pady=10)

    def trace_fun(new, *args):

        print new._var.get()
        Parent.classvar = new._var.get()


obj = Parent()

def main():
    obj.mainloop()

main()

2 个答案:

答案 0 :(得分:-1)

您已在此处覆盖了new变量:

   new = Frame.__init__(self)
   new = Toplevel(self)

执行这两个语句后,new等于Toplevel类的实例。

接下来,此代码执行:

new._var.trace("w", new.trace_fun)

,特别是:

new.trace_fun

因此,您有一个Toplevel实例尝试访问名为trace_fun的属性。错误消息告诉您Toplevel类没有任何名为trace_fun的属性。

编辑:

你不能在Toplevel实例上调用trace_fun。你也不能在父实例上调用trace_fun。因此,打印出您的程序副本,然后获得一支笔并圈出所有Toplevel实例的变量;然后圈出作为父实例的所有变量。您不能在任何这些变量上调用trace_fun。或者,圈出作为子实例的所有变量。你可以在这些变量上调用trace_fun。

以下是您可以执行的操作示例:

class Child:
    def do_stuff(self):     #1) self is an instance of class Child, i.e. the object that is calling this method
        self.trace_fun()    #2) The Child class defines a method named trace_fun()
                            #3) Therefore, self can call trace_fun()
        x = self.trace_fun  #4) ...or you can assign self.trace_fun to a variable
                            #5) ...or pass self.trace_fun to another function

    def trace_fun(self):
        print 'hello'

d = Chile()
d.do_stuff()

--output:--
hello

看起来您的两个帧之间没有父/子关系 - 因为子帧不使用从父帧继承的任何内容。所以你可以为你的应用创建两个独立的框架。这是一个例子:

import Tkinter as tk

class EntryFrame(tk.Frame):
    classvar = 0

    def __init__(self, root):
        tk.Frame.__init__(self, root) #Send root as the parent arg to Frame's __init__ method
        root.title("Parent Window")
        root.geometry("400x200")

        tk.Label(self, text="First").grid(row=0)
        tk.Label(self, text="Second").grid(row=1)

        e1 = tk.Entry(self)
        e2 = tk.Entry(self)

        e1.grid(row=0, column=1)
        e2.grid(row=1, column=1)

        button = tk.Button(self, text="Create", width=10, command=self.create_new_window)
        button.grid(row=2, column=0, sticky=tk.E + tk.W)

        self.grid()

    def create_new_window(self):
        RadioButtonFrame()


class RadioButtonFrame(tk.Frame):
    def __init__(self):
        new_top_level = tk.Toplevel()
        tk.Frame.__init__(self, new_top_level) #Send new_top_level as the parent arg to Frame's __init__ method

        new_top_level.title("Radio Button Window")
        new_top_level.geometry('400x300+0+300') # "width x height + x + y"

        self.int_var = int_var = tk.IntVar()
        int_var.trace("w", self.trace_func)
        int_var.set(0)

        rb1 = tk.Radiobutton(self, text = "Option 1", variable = int_var, value = 1)
        rb1.grid(row=0, column=0, sticky=tk.W, padx=10, pady=10)

        rb2 = tk.Radiobutton(self, text = "Option 2", variable = int_var, value = 2)
        rb2.grid(row=1, column=0, sticky=tk.W, padx=10, pady=10)

        button = tk.Button(self, text = 'Ok', command=new_top_level.destroy)
        button.grid(row=2, column=0, pady=10)

        self.grid()

    def trace_func(self, *args):
        radio_val = self.int_var.get()
        print radio_val

        EntryFrame.classvar = radio_val


def main():
    root = tk.Tk()
    my_frame = EntryFrame(root)
    root.mainloop()

main()

答案 1 :(得分:-1)

通过稍作修改,现在我的代码工作正常。为某人发布新代码与我之前的相同点。可以在以下代码中看到更改:

import Tkinter as tk

class Parent:
    classvar = 0

    def __init__(self, master):
        self.master = master
        self.frame = tk.Frame(self.master)
        self.master.title("Parent Window")
        self.master.geometry("400x100")
        self.frame.grid()

        self._button = tk.Button(self.frame, text="Create", width=10, command=self.new_window)
        self._button.grid(row=0, column=0, sticky=tk.E+tk.W)

    def new_window(self):
        self.child_window = tk.Toplevel(self.master)
        self.app = Child(self.child_window)

class Child(Parent):

    def __init__(self, master):

        self.master = master
        self.frame = tk.Frame(self.master)
        self.master.title("Child Window")
        self.frame.grid()

        self._var = IntVar()
        self._var.set(0)
        self._var.trace("w", self.trace_fun)

        self._radioButton = tk.Radiobutton(self.frame, text = "Option 1", variable = self._var, value = 1)
        self._radioButton.grid(row=0, column=0, sticky=W, padx=10, pady=10)

        self._radioButton2 = tk.Radiobutton(self.frame, text = "Option 2", variable = self._var, value = 2)
        self._radioButton2.grid(row=1, column=0, sticky=W, padx=10, pady=10)

        self._button = tk.Button(self.frame, text = 'Ok', command=self.master.destroy)
        self._button.grid(row=2, column=0, pady=10)

    def trace_fun(self, *args):
        Parent.classvar = self._var.get()
        print Parent.classvar


root = tk.Tk()
obj = Parent(root)

def main():
    root.mainloop()

main()