2

私の 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()

値を選択せず​​に閉じても問題ありませんが、値を選択した後に閉じようとすると、終了しますが、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: コマンド ラインからスクリプトを実行した場合にのみ、例外がスローされます。Idle には表示されません。

4

2 に答える 2

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.

基本的に、最後のウィンドウが閉じられてTkがファイナライズされた後、 の遅延呼び出しafterはキャンセルされず、完了できません。これは、プロシージャ/関数 '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()
于 2013-03-16T22:57:17.283 に答える
0

最近、同様の問題に遭遇しました。エラーメッセージはまったく同じです。Exit メソッドに a.quit() を追加することで解決しました。(それ以前は、このメソッドには a.destroy() しかありませんでした) おそらく、この質問はすでに解決済みです。しかし、シュレンクの答えは私にはうまくいきません。だから私は私の答えがそのような質問に別の手がかりを与えることを願っています

于 2015-06-19T13:33:21.020 に答える