使用来自其他窗口小部件输入字段的信息重新配置文本窗口小部件时的TypeError

时间:2015-02-23 12:00:17

标签: python user-interface tkinter widget typeerror

我有一个由两个小部件组成的Tkinter GUI,第一个是带有输入字段和按钮的小部件类,第二个是可滚动的文本小部件类。我将这两个小部件类组合在一起构成一个GUI。这些小部件类中的每一个都可以作为个人正确使用。

GUI的文本字段用于显示列表的特定索引的内容。我希望能够在输入字段中输入索引号,并且在按下按钮时,将重新配置文本字段中的文本以显示指定索引的列表内容。但是,当我按下按钮时,我收到以下错误消息:

  

" File" /Users/BioASys/BioasysDB/testgui.py" ;,第25行,在   fetch_update_text   article_review_widget_assembled.update_text(article_index)TypeError:   必须使用unbound方法update_text()进行调用   article_review_widget_assembled实例作为第一个参数(得到int   实例代替)"

当我初始化(mainloop)GUI时,我将文本小部件设置为显示列表的0索引。

我写了简单的代码来展示我的问题。我原来的代码太复杂了,不能在这里明智地发布。由于我原始代码中所有单个小部件的布局,有必要组合多个小部件类来实现我想要的小部件布局。

如果有人对如何让这两个小部件进行沟通有任何想法,我将非常感谢您的帮助。

这是我编写的简化代码,它展示了我遇到的问题。


from Tkinter import *

# This list contains the sample text 
# that is to be placed in the individual text widgets, 
# referenced by index
text_list = [['text0AAAAAAA'], ['text1AAAAAAA'], ['text2AAAAAAA']]

# This class creates the widget that will be designated top_left 
# in the article_review_widget_assembled widget

class article_review_entry_button_widget(Frame):

    def __init__(self, parent=None):
        Frame.__init__(self, parent)
        self.pack(expand=YES, fill=BOTH) 
        self.index = 2
        self.makeWidgets()

    def handleList(self, event):
        index = self.listbox.curselection()
        label = self.listbox.get(index)
        self.runCommand(label)

    def fetch(self):                                    
        # This def gets the value placed in the entry field
        print 'Input => "%s"' % self.ent.get()
        article_index = self.ent.get()

    def fetch_update_text(self):                        
        #  This def gets the value placed in the entry field 
        # and also attempts to access the update_text def 
        # to update the text in the  top_right widget
        print 'Input => "%s"' % self.ent.get()
        article_index = int(self.ent.get())
        # It is this line that is generating the TypeError

        # It is this line that is generating the TypeError
        article_review_widget_assembled.update_text(article_index)  

    def makeWidgets(self):
        self.ent = Entry(self)
        btn = Button(self, text='Next Article', command=self.fetch_update_text)
        self.ent.insert(0, 0)
        self.ent.pack(side=TOP, fill=BOTH)
        self.ent.focus()
        self.ent.bind('<Return>', (lambda event: self.fetch()))
        value = self.ent.get()
        btn.pack(side=TOP)

class ScrolledText(Frame):                      
    # This class creates a text widget that can be scrolled, 
    # I use this as the basis for the other text widgets in this GUI

    def __init__(self, parent=None, text='', file=None, 
                 width='', height=''):
        Frame.__init__(self, parent)
        self.pack(expand=YES, fill=BOTH) 
        self.width = width
        self.height = height
        self.makewidgets()
        self.settext(text, file)

    def makewidgets(self):
        sbar = Scrollbar(self)
        text = Text(self, relief=SUNKEN, width=self.width, height=self.height)
        sbar.config(command=text.yview)                  
        text.config(yscrollcommand=sbar.set)
        sbar.pack(side=RIGHT, fill=Y)last
        text.pack(side=LEFT, expand=YES, fill=BOTH) 
        self.text = text

    def settext(self, text='', file=None):
        self.text.delete('1.0', END)                    
        self.text.insert('1.0', text)
        self.text.mark_set(INSERT, '1.0') 
        self.text.focus()

    def gettext(self)
        return self.text.get('1.0', END+'-1c')

class article_review_widget_assembled(Frame):        
     # This class uses the previous classes 
     # to create the final assemnbeld GUI widget

    def __init__(self, parent=None):
        Frame.__init__(self, parent)
        self.pack(expand=YES, fill=BOTH)    
        self.text = text_list[0]
        self.makeWidgets()

    # This is the def that is called by the fetch_update_text def 
    # in the article_review_entry_button_widget class
    def update_text(index):
        self.top_right.configure(text=text_list[index])
        print "The index is:", index

    def makeWidgets(self):
        self.top_left = article_review_entry_button_widget(self).pack(side=LEFT)
        self.top_right = ScrolledText(self, text= self.text, width=50, height=15).pack(side=LEFT)

if __name__ == '__main__':
    #article_review_entry_button_widget().mainloop()
    #ScrolledTextComposite().mainloop()
    article_review_widget_assembled().mainloop()

1 个答案:

答案 0 :(得分:0)

您的问题是您创建了一个类(article_review_widget_assembled),创建了该类的实例(article_review_widget_assembled()),但后来尝试通过将其视为静态方法({{ 1}})。

正如您所定义的那样调用article_review_widget_assembled.update_text(article_index)的正确方法是通过该类的实例。这就是update_text告诉你的信息。 &#34;未绑定的方法&#34;意味着你正在调用一种被设计为“绑定”的方法。到一个实例,但你没有通过实例调用它。

解决方案是通过实例调用它。幸运的是,在您的情况下,您将TypeError: unbound method update_text() must be called with article_review_widget_assembled instance as first argument (got int instance instead)的引用作为article_review_entry_button_widget参数传递,因此如果您还设置parent,您似乎可以将其称为self. parent.update_text() }到self.parent参数的值:

parent

底线:当你得到一个&#34;未绑定的方法&#34;错误,这意味着您通过类而不是通过类的实例调用方法。如果遵循使用大写字符和小写实例启动类名的约定,则会更容易发现这些错误。这使您的代码更易于阅读和理解(例如:class article_review_entry_button_widget(Frame): def __init__(self, parent=None): self.parent = parent Frame.__init__(self, parent) ... def fetch_update_text(self): ... self.parent.update_text(article_index) 等)