'StringVar'对象没有属性'_report_exception'

时间:2015-09-18 10:32:07

标签: python python-3.x tkinter

我一直在处理这段代码,这是一个自动完成的条目小部件 当我测试程序时,它似乎输出

'StringVar'对象没有属性'_report_exception'

当我在输入框中输入内容并按退格键时。 我试图寻找这个问题的解决方案,但似乎没有人有这个输出。我听说有些人谈到类似的问题,他们让StringVar继承Tk所以属性会存在。对不起是一个菜鸟,但我真的不知道怎么做。

或者引起这个问题的其他问题是什么?

如果您正在寻找StringVar,它只在第15行。

from tkinter import *
import re


class AutocompleteEntry(Entry):
    def __init__(self, auto_list=[], *args, **kwargs):
        Entry.__init__(self, *args, **kwargs)
        # Find out maximum number of words can one suggestion include in autocomplete list
        # This will be used later
        self.auto_list = auto_list
        auto_list = [item.split() for item in auto_list]
        self.max_words = len(max(auto_list, key=len))

        # Get the text from entry when there is changes made to entry
        self.var = self['textvariable'] = StringVar()
        self.var.trace('w', self.changed)

        # Set listbox(suggestion box) to doesn't exist
        self.list_exist = False

        # Binding keys use to control selection
        self.bind('<Return>', self.KeyReturn)
        self.bind('<Tab>', self.KeyTab)

    def KeyReturn(self, event):
        if self.list_exist:
            # Fetch the current select value
            value = self.list.get(self.list_index)

            ## Clear the content of Entry and replace with selected value
            self.delete(0,"end")
            self.insert(0, value)

            # Destroy the list and state that it doesn't exist anymore
            self.list.destroy()
            self.list_exist = False

    def KeyTab(self, event):
        if self.list_exist:
            # Clear the last selection before proceeding
            self.list.selection_clear(self.list_index)


            # Make selection to the next one
            self.list_index += 1

            # list index started from -1 and increment by 1, causes div by 0 error
            try:
                self.list_index = self.list_index%(self.list.size()-1)
            except ZeroDivisionError:
                self.list_index = 0

            self.list.selection_set(self.list_index)
            self.list.activate(self.list_index)
            # This special break prevent widget switch when list is there
            return 'break'

        # If list is not there, allow switch by pressing tab
        return 
    def regex_match(self,typed):
        matches = []
        patterns = []

        for words in typed:
            # Make sure it's not spaces made up the typing
            if words.strip != '':
                patterns.append(r'(%s)'%(words))

        # Sort the pattern list according to length of words, from longest to shortest
        patterns.sort(key=len,reverse=True)
        # Compile the patterns and ignore cases
        patterns = [re.compile(pattern,re.IGNORECASE) for pattern in patterns]
        # Matching done from longest pattern to shortest
        for pattern in patterns:
            for phrase in self.auto_list:
                result = pattern.match(phrase)
                if result == None:
                    continue
                else:
                    matches.append(phrase)

        return matches

    def changed(self,name,index,mode):
        # Get all the words already been typed up so far and split into list by space
        words = self.var.get().split()

        # If there is nothing in the entry and list exist, destroy list 
        if words == [] and self.list_exist:
            self.list.destroy()
            self.list_exist = False

        ## There are more code to add here if we don't want to autocomplete only the last phrase in the text field

        # Getting typed words, getting all the possibilities
        typed = []
        for i in range(1,self.max_words):
            # break if max words > what currently typed and when all possibility are obtained, otherwise may cause index out of range
            if i > len(words):
                break
            typed.append(' '.join(words[-i:]))

        # Only proceed matching method if typed list is not empty
        if len(typed) > 0:
            matches = self.regex_match(typed)


        # Manage autocompletion list box

        self.manage_auto(matches)

    def manage_auto(self, matches):
        # if there is no match but list is there, take it out
        if len(matches) == 0 and self.list_exist:
            self.list.destroy()
            self.list_exist = False
        # if there are suggestions but no list, create list and insert matches
        elif len(matches) > 0 and not self.list_exist:
            # Create the listbox for suggestions
            self.list = Listbox(width = self['width'])
            self.list.place(x=self.winfo_x(),y=self.winfo_y()+self.winfo_height())
            self.list_exist = True
            # Insert values
            for match in matches:
                self.list.insert("end",match)
            self.list_index = -1

        elif len(matches) > 0 and self.list_exist:
            # Replace the matches by first deleting all
            self.list.delete(0,"end")
            # Now insert the new matches
            for match in matches:
                self.list.insert("end",match)
            self.list_index = -1


if __name__ == '__main__':

    items = ['Cash and Equivalent', 'Marketable Securities', 'Trade Receivables', 'Bad Debt Allowance', 'Inventory', 'Others Current Asset', 'Tangibles', 'Intangibles', 'Other Intangibles ', 'Deferred Tax Asset', 'Other Non-Current Asset', 'Current Debt', 'Account Payable', 'Provisions', 'Other Current Liability', 'Non-Current Debt', 'Deferred Tax Liability', 'Other Non-Current Liability', 'Ordinary Share Capital', 'Other Capital', 'Retained Earnings', 'Other Reserves', 'Operating Revenue', 'Cost of Sales', 'Selling, General and Administrative Expenses', 'Other Operating Expense', 'Depreciation and Amortization', 'Other Income', 'Other Expense', 'Operating Cash Flow', 'Purchase/Sale of Non-Current Asset', 'Capital Expenditures', 'Other Investment/Acquisition', 'Net Interest Cost', 'Net Debt Issuance(Repayment)', 'Net Share Issuance(Repurchase)', 'Dividends', 'Investment Income', 'Net Interest Expense', 'Tax Expense']


    root = Tk()

    a = AutocompleteEntry(items, root, width = 150)
    b = AutocompleteEntry(items, root, width = 150)
    a.pack()
    b.pack()
    a.focus()


    root.mainloop()

这是完整的错误输出

Traceback (most recent call last):
  File "C:\Python34\lib\tkinter\__init__.py", line 1533, in __call__
    return self.func(*args)
  File "C:\Users\Kung\Desktop\Autocompletion\Autocompletion.pyw", line 110, in changed
    self.manage_auto(matches)
UnboundLocalError: local variable 'matches' referenced before assignment

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Kung\Desktop\Autocompletion\Autocompletion.pyw", line 151, in <module>
    root.mainloop()
  File "C:\Python34\lib\tkinter\__init__.py", line 1120, in mainloop
    self.tk.mainloop(n)
  File "C:\Python34\lib\tkinter\__init__.py", line 1537, in __call__
    self.widget._report_exception()
AttributeError: 'StringVar' object has no attribute '_report_exception'

1 个答案:

答案 0 :(得分:0)

错误消息告诉您问题的确切位置和位置:

  File "C:\Users\Kung\Desktop\Autocompletion\Autocompletion.pyw", line 110, in changed
    self.manage_auto(matches)
UnboundLocalError: local variable 'matches' referenced before assignment

问题在于这段代码:

if len(typed) > 0:
    matches = self.regex_match(typed)


# Manage autocompletion list box

self.manage_auto(matches)

如果输入字段为空,则未设置matches。当您到达下一行时,您尝试使用matches。对于matches为零的情况,您需要为len(typed)设置默认值。