Python:如何访问类';来自模块的属性

Python:如何访问类';来自模块的属性,python,tkinter,attributeerror,Python,Tkinter,Attributeerror,我有一个主文件,主要包含GUI(Tkinter代码)。一个窗口,具有标签、一个文本区域,其中文本在用户操作时得到更新,以及一个按钮 # ~/main.py import Tkinter import buttonevent from itertools import cycle msglist = ['main_msg1\n', 'main_msg2\n', 'main_msg3\n', 'main_msg4\n'] class Root(object): def __init_

我有一个主文件,主要包含GUI(Tkinter代码)。一个窗口,具有
标签
、一个
文本
区域,其中文本在用户操作时得到更新,以及一个
按钮

# ~/main.py
import Tkinter
import buttonevent
from itertools import cycle

msglist = ['main_msg1\n', 'main_msg2\n', 'main_msg3\n', 'main_msg4\n']


class Root(object):

    def __init__(self, master):
        self.msglist = cycle(msglist)
        self.master = master
        self.frame1 = Tkinter.Frame(master)
        self.frame1.pack()
        Root.status = Tkinter.StringVar()
        self.status_info = Tkinter.Label(self.frame1, textvariable=Root.status)
        self.status_info.pack()
        Root.status.set("Set by constructor")

        self.frame2 = Tkinter.Frame(master)
        self.frame2.pack()
        Root.textinfo = Tkinter.Text(self.frame2, width=20, height=10)
        Root.textinfo.insert(Tkinter.END, 'message 1')
        Root.textinfo.config(font='Arial')
        Root.textinfo.pack()
        Root.textinfo.config(bg=master.cget('bg'), relief=Tkinter.SUNKEN)
        Root.textinfo.configure(state='disabled')

        self.frame3 = Tkinter.Frame(master)
        self.frame3.pack()
        self.button = Tkinter.Button(self.frame3, text='Ok', command=self.ok)
        self.button.pack()

    def ok(self):
        text_info(self.msglist.next())
        buttonevent.do_event()
        buttonevent.do_stuff()


def text_info(msg):
    Root.textinfo.configure(state='normal')
    Root.textinfo.insert(Tkinter.END, msg)
    Root.textinfo.see(Tkinter.END)
    Root.textinfo.configure(state='disabled')


if __name__ == '__main__':
    root = Tkinter.Tk()
    main_window = Root(root)
    root.mainloop()
用户操作是在不同的文件上定义的

# ~/buttonevent.py

from itertools import cycle
import main

do_msg = ['do_msg1\n', 'do_msg2\n', 'do_msg3\n', 'do_msg4\n']
msg = cycle(do_msg)


def do_event():
    # do something
    main.text_info(msg.next())


def do_stuff():
    # do something
    print 'doing stuff'
以前的代码是在一个文件中,现在我试图根据它的功能将其编写为一个多文件。基本上,当用户执行某项操作时,将在
文本
区域显示一条消息。由于
Text
字段显示消息,并且在每次显示/活动/更新时都有一些共性,因此我在主文件中为它创建了一个函数作为
Text\u info

如果我想在
文本
字段上发送不同的消息以从不同的文件进行更新,。。例如,在
buttonevent.py
文件中,如何实现它

当我运行它时,我得到的错误是

$ python main.py
do_msg1

Exception in Tkinter callback
Traceback (most recent call last):
  File "/home/miniconda2/lib/python2.7/lib-tk/Tkinter.py", line 1537, in __call__
    return self.func(*args)
  File "main.py", line 38, in ok
    buttonevent.do_event()
  File "/home/buttonevent.py", line 14, in do_event
    main.text_info(xx)
  File "/home/main.py", line 51, in text_info
    Root.textinfo.configure(state='normal')
AttributeError: type object 'Root' has no attribute 'textinfo'
  • 如何从不同的py文件调用主py文件中的函数
  • 对于
    main.py
    文件中的
    文本信息
    ,我应该使用
    还是
    函数
  • 如果这不是正确的编码方式,请纠正我

  • 通过将根实例的引用作为函数的参数,可以实现所需的功能:

    而不是指定给根类:

    Root.status = Tkinter.StringVar()
    
    将其分配给根实例:

    self.status = Tkinter.StringVar()
    
    没有理由将其分配给根类而不是实例本身,因为它的所有权也是根实例的一部分:触发要更新的事件的是根实例的组件(Tkinter部分)。 然后,您可以将self作为buttonevent的参数:

    def ok(self):
        text_info(self.msglist.next())
        buttonevent.do_event(self)
        buttonevent.do_stuff(self)
    
    然后,您可以将文本信息作为课程的一部分:

    class Root(object):
    
        ...
    
        def text_info(self, msg):
            self.textinfo.configure(state='normal')
            self.textinfo.insert(Tkinter.END, msg)
            self.textinfo.see(Tkinter.END)
    
    并将按钮Event更改为:

    def do_event(root_instance):
        # do something
        root_instance.text_info(msg.next())
    
    所有的“根”,改为“自我” main.py

    钮扣

    # ~/buttonevent.py
    
    from itertools import cycle
    import main
    
    do_msg = ['do_msg1\n', 'do_msg2\n', 'do_msg3\n', 'do_msg4\n']
    msg = cycle(do_msg)
    curmsg=msg.next() # Add this variable to call main.py to first click event
    
    def do_event():
        # do something
        global curmsg #to edit variable value you must call it as global
        curmsg=msg.next() #Changing variable value for each click
        #Removed text_info function from main.py it is not necessary.
    def do_stuff():
        # do something
        print 'doing stuff'
    

    textinfo
    是一个类属性,在初始化至少一个根类实例之前不会设置该属性。。在使用text_info函数之前,需要在原始文件中创建根类的实例。除非至少实例化了一个对象,否则永远不会执行
    \uuuuu init\uuuu
    方法中的代码。啊哈。问题是你有
    如果uuu name uuu=='uuu main uuu':
    这意味着在导入main时,之后的一切都不会被执行…如果你解释一下你所做的更改,你的答案会好得多。否则,我们将被迫逐行读取您的代码,将每行代码与原始代码进行比较。无需使用text\u info函数。您可以删除此函数。您的问题是变量传输。我在buttonevent.py脚本中添加了“curmsg”变量。并在根类的“ok”函数中将其称为“buttonevent.curmsg”。并删除buttonevent.py脚本中do_事件函数的任何函数调用,因为您在初始化根类中将click事件定义为“Ok”。因此,当点击按钮“ok”时,函数从buttonevent脚本调用currentmsg。这个答案与OP代码的行为方式不同<代码>自我。msglist从不循环。所有更改都会被注意到。从buttonevent.py获取消息
    # ~/buttonevent.py
    
    from itertools import cycle
    import main
    
    do_msg = ['do_msg1\n', 'do_msg2\n', 'do_msg3\n', 'do_msg4\n']
    msg = cycle(do_msg)
    curmsg=msg.next() # Add this variable to call main.py to first click event
    
    def do_event():
        # do something
        global curmsg #to edit variable value you must call it as global
        curmsg=msg.next() #Changing variable value for each click
        #Removed text_info function from main.py it is not necessary.
    def do_stuff():
        # do something
        print 'doing stuff'