2010-11-24 19 views
5

我正在使用Python 2.6.x和TKinter在Windows XP上工作。在应用程序中使用文本小部件,但缺少标准弹出式菜单(剪切,复制,粘贴,删除,全选)。如何使其显示?Python中的Stardand上下文菜单当鼠标右键按下时,TKinter文本小部件

+0

右键单击一个上下文菜单,以及出现在这样的菜单上出现的内容没有被广泛标准化。在支持它的平台上,许多应用程序都有一个约定(如编辑文本)。 'tkinter` API是平台独立的,所以如果你想要这个功能,我相信你必须编写(或者查找)实现它的代码或者接近你想要的代码。 – martineau 2010-11-24 19:21:34

回答

4

我找到了一种方法,这要归功于this post。我做了一些修改。在底部有一个最小的main来尝试它。

from Tkinter import * 

def rClicker(e): 
    ''' right click context menu for all Tk Entry and Text widgets 
    ''' 

    try: 
     def rClick_Copy(e, apnd=0): 
      e.widget.event_generate('<Control-c>') 

     def rClick_Cut(e): 
      e.widget.event_generate('<Control-x>') 

     def rClick_Paste(e): 
      e.widget.event_generate('<Control-v>') 

     e.widget.focus() 

     nclst=[ 
       (' Cut', lambda e=e: rClick_Cut(e)), 
       (' Copy', lambda e=e: rClick_Copy(e)), 
       (' Paste', lambda e=e: rClick_Paste(e)), 
       ] 

     rmenu = Menu(None, tearoff=0, takefocus=0) 

     for (txt, cmd) in nclst: 
      rmenu.add_command(label=txt, command=cmd) 

     rmenu.tk_popup(e.x_root+40, e.y_root+10,entry="0") 

    except TclError: 
     print ' - rClick menu, something wrong' 
     pass 

    return "break" 


def rClickbinder(r): 

    try: 
     for b in [ 'Text', 'Entry', 'Listbox', 'Label']: # 
      r.bind_class(b, sequence='<Button-3>', 
         func=rClicker, add='') 
    except TclError: 
     print ' - rClickbinder, something wrong' 
     pass 


if __name__ == '__main__': 
    master = Tk() 
    ent = Entry(master, width=50) 
    ent.pack(anchor="w") 

    #bind context menu to a specific element 
    ent.bind('<Button-3>',rClicker, add='') 
    #or bind it to any Text/Entry/Listbox/Label element 
    #rClickbinder(master) 

    master.mainloop() 
+0

在上面的示例中,`rClickbinder`显得多余。或者我想你应该在调用`mainloop()`之前调用`rClickbinder(master)`? – scorpiodawg 2012-04-16 18:30:32

+0

@scorpiodawg你是对的,我编辑了答案:rClickbinder在那里,因为它是一个有用的方法,使列出的类型的每个元素的上下文菜单。 – bluish 2012-04-17 06:56:26

1

想到我会分享我的解决方案,基于在stackoverflow几个代码片段。它包括一个最小的应用程序来测试:

编辑:类绑定可能无法正常工作。如果是这种情况,请使用常规绑定并在select_all函数中返回“break”。

import Tkinter as tk 

if 1: # nice widgets 
    import ttk 
else: 
    ttk = tk 

class EntryPlus(ttk.Entry): 
    def __init__(self, *args, **kwargs): 
     ttk.Entry.__init__(self, *args, **kwargs) 
     _rc_menu_install(self) 
     # overwrite default class binding so we don't need to return "break" 
     self.bind_class("Entry", "<Control-a>", self.event_select_all) 
     self.bind("<Button-3><ButtonRelease-3>", self.show_menu) 

    def event_select_all(self, *args): 
     self.focus_force() 
     self.selection_range(0, tk.END) 

    def show_menu(self, e): 
     self.tk.call("tk_popup", self.menu, e.x_root, e.y_root) 

class TextPlus(tk.Text): 
    def __init__(self, *args, **kwargs): 
     tk.Text.__init__(self, *args, **kwargs) 
     _rc_menu_install(self) 
     # overwrite default class binding so we don't need to return "break" 
     self.bind_class("Text", "<Control-a>", self.event_select_all) 
     self.bind("<Button-3><ButtonRelease-3>", self.show_menu) 

    def event_select_all(self, *args): 
     self.focus_force()   
     self.tag_add("sel","1.0","end") 

    def show_menu(self, e): 
     self.tk.call("tk_popup", self.menu, e.x_root, e.y_root) 


def _rc_menu_install(w): 
    w.menu = tk.Menu(w, tearoff=0) 
    w.menu.add_command(label="Cut") 
    w.menu.add_command(label="Copy") 
    w.menu.add_command(label="Paste") 
    w.menu.add_separator() 
    w.menu.add_command(label="Select all")   

    w.menu.entryconfigure("Cut", command=lambda: w.focus_force() or w.event_generate("<<Cut>>")) 
    w.menu.entryconfigure("Copy", command=lambda: w.focus_force() or w.event_generate("<<Copy>>")) 
    w.menu.entryconfigure("Paste", command=lambda: w.focus_force() or w.event_generate("<<Paste>>")) 
    w.menu.entryconfigure("Select all", command=w.event_select_all)   


if __name__ == "__main__": 

    class SampleApp(tk.Tk): 
     def __init__(self, *args, **kwargs): 
      tk.Tk.__init__(self, *args, **kwargs) 

      self.entry = EntryPlus(self) 
      self.text = TextPlus(self) 

      self.entry.pack() 
      self.text.pack() 

      self.entry.insert(0, "copy paste") 
      self.text.insert(tk.INSERT, "copy paste") 

    app = SampleApp() 
    app.mainloop() 
1

由于Gonzo的代码和蓝色0​​我textwidget右键工作。 我没有50个声望,但我遇到了一个问题,我面临的问题是,无论点击的位置如何,右按钮都会触发该功能。 想通方式:

def show_menu(self, e): 
     if e.widget==self.text: 
      self.tk.call("tk_popup", self.menu, e.x_root, e.y_root) 

现在,只有当你点击文本插件的右键的弹出窗口将被触发。

相关问题