Python tkinter.ttk组合框在退出时抛出异常

时间:2013-03-16 11:51:01

标签: python combobox tkinter ttk

在我的Python 3.3代码中,我使用了ttk库中的一些组合框,它们运行正常但是如果我使用它们中的任何一个,当我用X按钮关闭窗口时出现异常。这是一个例子:

from tkinter import Tk,Label,Button
from tkinter import ttk
from tkinter.ttk import Combobox

def cbox_do(event):
    'Used for cbox.'
    clabel.config(text=cbox.get())

a = Tk()
cbox = Combobox(a, value=('Luke','Biggs','Wedge'), takefocus=0)
cbox.bind("<<ComboboxSelected>>", cbox_do)
cbox.pack()
clabel = Label(a)
clabel.pack()
a.mainloop()

如果你在没有选择值的情况下关闭它,那么everithing很好,但是在选择一个值后尝试关闭它,它会退出但是会在python命令行中输出以下错误:

can't invoke "winfo" command:  application has been destroyed
    while executing
"winfo exists $w"
    (procedure "ttk::entry::AutoScroll" line 3)
    invoked from within
"ttk::entry::AutoScroll .41024560"
    (in namespace inscope "::" script line 1)
    invoked from within
"::namespace inscope :: {ttk::entry::AutoScroll .41024560}"
    ("uplevel" body line 1)
    invoked from within
"uplevel #0 $Repeat(script)"
    (procedure "ttk::Repeat" line 3)
    invoked from within
"ttk::Repeat"
    ("after" script)

我该如何解决?如果您能提供任何帮助,我将不胜感激。

更新1: 我的Python版本是v3.3,我使用捆绑的Tcl / Tk和Tkinter。我尝试了x86和x64版本。

更新2: 仅当我从命令行运行脚本时才会抛出异常。它不会出现在空闲中。

2 个答案:

答案 0 :(得分:4)

这是ttk中使用的Tcl / Tk绑定代码的问题。

在典型的python Tkinter安装中,tcl / tk8.5 / ttk / entry.tcl文件中的注释暗示了这个问题:

## AutoScroll
#   Called repeatedly when the mouse is outside an entry window
#   with Button 1 down.  Scroll the window left or right,
#   depending on where the mouse is, and extend the selection
#   according to the current selection mode.
#
# TODO: AutoScroll should repeat faster (50ms) than normal autorepeat.
# TODO: Need a way for Repeat scripts to cancel themselves.

基本上,after的延迟调用未被取消,并且在最后一个窗口关闭并且Tk完成后不能再完成,因为过程/函数'winfo'不再存在。当你运行IDLE时,仍然有一个窗口,所以Tk没有最终确定并且错误没有出现。

您可以使用WM_DELETE_WINDOW消息上的绑定来解决此问题,该消息会停止重复计时器。该代码将是(在Tcl / Tk中):

proc shutdown_ttk_repeat {args} {
    ::ttk::CancelRepeat
}
wm protocol . WM_DELETE_WINDOW shutdown_ttk_repeat

对于Tkinter,它应该以类似的方式工作:

from tkinter import Tk,Label,Button
from tkinter import ttk
from tkinter.ttk import Combobox

def cbox_do(event):
    'Used for cbox.'
    clabel.config(text=cbox.get())

a = Tk()
cbox = Combobox(a, value=('Luke','Biggs','Wedge'), takefocus=0)
cbox.bind("<<ComboboxSelected>>", cbox_do)
cbox.pack()
clabel = Label(a)
clabel.pack()

def shutdown_ttk_repeat():
    a.eval('::ttk::CancelRepeat')
    a.destroy()

a.protocol("WM_DELETE_WINDOW", shutdown_ttk_repeat)
a.mainloop()

答案 1 :(得分:0)

我最近遇到过类似的问题。错误消息完全相同。 我通过在Exit方法中添加a.quit()解决了这个问题。 (在此之前,此方法中只有a.destroy()) 也许你已经解决了这个问题。但施莱克的回答对我不起作用。所以我希望我的回答可以为这样的问题提供另一个线索