python tkinter treeview not allowing modal window with direct binding like on_rightclick

半腔热情 提交于 2020-01-26 04:11:47

问题


Treeview with mouseclick binding that directly calls a function to open a modal window fails on grab_set()

tkinter.TclError: grab failed: window not viewable

The same works perfectly well if the mouseclick first opens a popup menu that calls the modal window function.

Is it not possible to open a modal window directly from a mouseclick (preferably doubleclick)?

Linux Mint 17/Ubuntu 14.04, 64bit, Python 3

My simple code example below. Please note that though I call two different functions, the code in each is essentially the same. When called from the popup menu it gives a modal window, when called directly from the treeview, it fails miserably. Is that expected behavior?

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

回答1:


I use Linux Mint 17/Ubuntu 14.04, 64bit, Python 3 too.

You can always check source code of existing dialogs and see how it works.

For example check filedialogs - path to file with source code:

import tkinter.filedialog

print(tkinter.filedialog.__file__)

# /usr/lib/python3.5/tkinter/filedialog.py

and you will see

self.top.wait_visibility() # window needs to be visible for the grab
self.top.grab_set()

So you have to use wait_visibility() before grab_set()

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"

    pup.wait_visibility() # <-----

    pup.grab_set()
    self.root.wait_window(pup)


来源:https://stackoverflow.com/questions/40861638/python-tkinter-treeview-not-allowing-modal-window-with-direct-binding-like-on-ri

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!