【发布时间】:2016-11-29 09:03:40
【问题描述】:
在grab_set() 上直接调用函数以打开模式窗口的带有鼠标单击绑定的 Treeview 失败
tkinter.TclError: grab failed: window not viewable
如果鼠标点击首先打开一个调用模态窗口函数的弹出菜单,同样的效果也很好。
难道不能直接通过鼠标点击(最好是双击)打开模态窗口吗?
Linux Mint 17/Ubuntu 14.04、64 位、Python 3
下面是我的简单代码示例。请注意,虽然我调用了两个不同的函数,但每个函数中的代码本质上是相同的。当从弹出菜单调用时,它会给出一个模态窗口,当直接从树视图调用时,它会惨遭失败。这是预期的行为吗?
import tkinter as tk
from tkinter import ttk
class PopupWindow(tk.Toplevel):
def __init__(self,parent):
tk.Toplevel.__init__(self,parent)
self.parent=parent
self.protocol("WM_DELETE_WINDOW",self.destroy)
self.attributes('-topmost',True)
self.transient()
mainWindow=tk.Frame(self)
tFrame=tk.Frame(mainWindow)
self.tLabel=tk.Label(tFrame,text='Is this modal?',height=3,bd=10)
self.tLabel.pack()
self.tLabel2=tk.Label(tFrame,text=' ',height=3,bd=10)
self.tLabel2.pack()
bFrame=tk.Frame(mainWindow,bd=5)
bOK=tk.Button(bFrame,bd=1,text='Ok',command=self.destroy)
bOK.pack(side='left')
tFrame.grid(row=0,column=0)
bFrame.grid(row=1,column=0,sticky=tk.E)
mainWindow.pack()
class App:
def __init__(self):
self.root = tk.Tk()
self.tree = ttk.Treeview()
self.tree.pack()
for i in range(10):
self.tree.insert("", "end", text="Item %s" % i)
self.tree.bind("<Double-1>", self.onDoubleClick)
self.tree.bind("<Button-3>", self.onRightClick)
self.aMenu = tk.Menu(self.root, tearoff=0)
self.aMenu.add_command(label="Show 'Modal' Window",
command=lambda selection=self.tree.selection(): self.showIsModal(selection))
self.aMenu.add_separator()
self.root.mainloop()
def onRightClick(self, event):
try:
self.aMenu.selection = self.tree.identify_row(event.y)
self.aMenu.post(event.x_root, event.y_root)
finally:
self.aMenu.grab_release()
def showIsModal(self, item):
pup=PopupWindow(self.root);
pup.tLabel2['text']="Absolutely!"
pup.grab_set()
self.root.wait_window(pup)
def onDoubleClick(self, event):
item = self.tree.identify('item',event.x,event.y)
self.tree.grab_release()
self.showIsNotModal(item)
def showIsNotModal(self, item):
print("you clicked on", self.tree.item(item,"text"))
pup=PopupWindow(self.root);
pup.tLabel2['text']="Sadly no: grab_set() fails"
# following line will fail:
pup.grab_set()
self.root.wait_window(pup)
if __name__ == "__main__":
app = App()
【问题讨论】:
-
可能与操作系统、python 版本或 tcl/k 版本有关。似乎在 Windows、python 3.5.2、tcl/tk 8.6 中对我有用。
标签: python tkinter modal-dialog treeview