我一直在处理这段代码,这是一个自动完成的条目小部件 当我测试程序时,它似乎输出
'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'
答案 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)
设置默认值。