7
votes

Menu contextuel standard dans le widget de texte Python Tkinter lorsque vous appuyez sur le bouton droit de la souris

Je travaille sur Windows XP, avec Python 2.6.x et Tkinter. Utilisation d'un widget de texte dans l'application, mais le menu contextuel standard (couper, copier, coller, supprimer, sélectionner tout) est manquant. Comment faire apparaître?


1 commentaires

Cliquez avec le bouton droit de la souris pour un menu contextuel, ainsi que ce qui apparaît dans un tel menu si l'on apparaît n'est pas largement normalisé. Sur les plates-formes qui l'appuient, il y a beaucoup de convention pour certaines applications (comme édition de texte). Le tkinter API est indépendant de la plate-forme, donc si vous voulez cette fonctionnalité, je pense que vous devrez écrire (ou trouver) le code qui l'applique ou quelque chose près de ce que vous voulez.


3 Réponses :


7
votes

J'ai trouvé un moyen, grâce à Ce message . J'ai fait des modifications. À la partie inférieure, il y a un minimal principal code> pour l'essayer.

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


2 commentaires

Le rclicker semble superflu dans cet exemple ci-dessus. Ou je suppose que vous devriez appeler rclickerder (maître) avant d'appeler mainloop () ?


@scorpiodawg Vous avez raison, j'ai modifié la réponse: RClickBinder est là car c'est une méthode utile pour activer le menu contextuel sur chaque élément des types répertoriés.



3
votes

pensais que je partagerais ma solution, en fonction de plusieurs extraits de code sur Stackoverflow. Il comprend une application minimale à tester:

Edit: Les reliures de classe ne peuvent pas fonctionner. Si c'était le cas, utilisez des liaisons normales et renvoyez «Break» dans les fonctions Select_all. P>

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 commentaires

self.tk.call ("tk_popup", self.menu, e.x_root, e.y_root) peut être transformé en self.menu.tk_popup plus lisible (e.x_root, e.y_root). Ht



1
votes

Grâce au code de Gonzo et au bleuâtre '', Mon bouton droit TextWidget a fonctionné. Je n'ai pas 50 réputations, mais j'ai eu un problème que j'ai confronté que le bouton droit déclenchera la fonction quel que soit l'emplacement du point cliqué. a compris que par: xxx

Maintenant, seule la fenêtre contextuelle du bouton droit sera déclenchée lorsque vous cliquez sur le widget Texte.


0 commentaires