2010-11-24 21 views
5

私はPython 2.6.xとTKinterを使ってWindows XPで作業しています。アプリでテキストウィジェットを使用しますが、標準のポップアップメニュー(切り取り、コピー、貼り付け、削除、すべて選択)はありません。それを現われるには?PythonのStardandコンテキストメニューTKinterマウス右ボタンを押したときのテキストウィジェット

+0

コンテキストメニューを右クリックすると、そのメニューに表示される内容は広く標準化されていません。それをサポートするプラットフォームでは、(テキストの編集のような)特定のアプリケーションのための規約がたくさんあります。 'tkinter' APIはプラットフォームに依存しないので、この機能が必要な場合は、実装しているコードや必要なものに近いものを書かなければなりません。 – martineau

答えて

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

+0

@scorpiodawgあなたが正しいです、私は答えを編集しました:rClickbinderは、リストされたタイプのすべての要素に対してコンテキストメニューを有効にするのに便利な方法なので、そこにあります。 – bluish

1

私は、stackoverflowのいくつかのコードスニペットに基づいて私の解決策を共有します。テストするための最小限のアプリケーションが含まれています:

編集:クラスバインディングが機能しない可能性があります。その場合、通常のバインディングを使用し、select_all関数で "break"を返します。ハメ撮りのコードと青みがかった'<Control-c>',私textwidget右ボタンに

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

self.tk.call( "tk_popup"、self.menu、e.x_root、e.y_root)は、より読みやすいself.menu.tk_popup(e.x_root、e.y_root)に変換できます。 HTH –

1

おかげで働いていました。 私は50の評判を持っていませんが、私は、クリックされたポイントの位置に関係なく、右のボタンが機能を引き起こすという問題に直面しました。あなたがテキストウィジェットをクリックすると今だけ右ボタンのポップアップがトリガされます

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

: はでそれを考え出しました。