Создать раскрывающееся меню на месте щелчка - Python Tkinter [duplicate]

"ABABAB".replace(/B/g, "A");

Как всегда: не используйте regex, если вам не нужно. Для простой замены строки идиома:

'ABABAB'.split('B').join('A')

Тогда вам не нужно беспокоиться о проблемах с цитированием, упомянутых в ответе Граценота.

21
задан martineau 17 April 2017 в 14:45
поделиться

2 ответа

Вы создали бы экземпляр Menu и напишите функцию, которая вызывает свой метод post() или tk_popup() .

В документации tkinter в настоящее время нет информации о tk_popup(). Прочитайте документацию Tk для описания или источника:

library/menu.tcl в источнике Tcl / Tk :

::tk_popup --
This procedure pops up a menu and sets things up for traversing
the menu and its submenus.

Arguments:
menu  - Name of the menu to be popped up.
x, y  - Root coordinates at which to pop up the menu.  
entry - Index of a menu entry to center over (x,y).  
        If omitted or specified as {}, then menu's  
        upper-left corner goes at (x,y).  

tkinter/__init__.py в источнике Python :

def tk_popup(self, x, y, entry=""):
    """Post the menu at position X,Y with entry ENTRY."""
    self.tk.call('tk_popup', self._w, x, y, entry)

Вы связываете свою функцию с помощью щелчка правой кнопкой мыши через: the_widget_clicked_on.bind("<Button-3>", your_function) .

Однако число, связанное с щелчком правой кнопкой мыши, не одинаково на каждой платформе.

library/tk.tcl в источнике Tcl / Tk :

On Darwin/Aqua, buttons from left to right are 1,3,2.  
On Darwin/X11 with recent XQuartz as the X server, they are 1,2,3; 
other X servers may differ.

Вот пример, который я написал, который добавляет контекстное меню в Listbox:

import tkinter # Tkinter -> tkinter in Python 3

class FancyListbox(tkinter.Listbox):

    def __init__(self, parent, *args, **kwargs):
        tkinter.Listbox.__init__(self, parent, *args, **kwargs)

        self.popup_menu = tkinter.Menu(self, tearoff=0)
        self.popup_menu.add_command(label="Delete",
                                    command=self.delete_selected)
        self.popup_menu.add_command(label="Select All",
                                    command=self.select_all)

        self.bind("<Button-3>", self.popup) # Button-2 on Aqua

    def popup(self, event):
        try:
            self.popup_menu.tk_popup(event.x_root, event.y_root, 0)
        finally:
            self.popup_menu.grab_release()

    def delete_selected(self):
        for i in self.curselection()[::-1]:
            self.delete(i)

    def select_all(self):
        self.selection_set(0, 'end')


root = tkinter.Tk()
flb = FancyListbox(root, selectmode='multiple')
for n in range(10):
    flb.insert('end', n)
flb.pack()
root.mainloop()

Использование grab_release() наблюдалось в примере на effbot

G9]. Его влияние может быть не одинаковым для всех систем.

31
ответ дан Honest Abe 19 August 2018 в 12:16
поделиться
  • 1
    спасибо, это было действительно полезно! Мне нужно было сделать что-то странное / другое, чтобы отобразить всплывающее меню. Я оказался привязанным к Tk. – tijko 18 August 2012 в 03:34
  • 2
    @tijko Вы можете использовать New Reference Tech Reference в качестве дополнительного источника информации. – Honest Abe 18 August 2012 в 04:37
  • 3
    Я столкнулся с этой ссылкой, узнав о Tkinter несколько раз, и там есть хорошие учебные пособия. Я начинаю думать о том, как я это делаю. Сначала я думал о том, чтобы создать контекстное меню, щелкнув правой кнопкой мыши в Tkinter. Я мог бы использовать какую-то функцию копирования и вставки, которая будет переноситься на мою систему и на браузер / блокнот. – tijko 18 August 2012 в 04:43
  • 4
    На Ubuntu 16.10, работающем с Python 3.5.2, tkinter 8.6, оператор self.aMenu.post (event.x_root, event.y_root) оставляет меню открытым, если пользователь не выбирает пункт меню. Я обнаружил, что замена его на self.aMenu.tk_popup (event.x_root, event.y_root) решает проблему: нажатие ESC или щелчок в другом месте автоматически удаляет его, как ожидалось. – Alberto Vassena 28 November 2016 в 18:46

Я внес некоторые изменения в код контекстного меню выше, чтобы настроить мой запрос, и я думаю, что было бы полезно поделиться:

Версия 1:

import tkinter as tk
from tkinter import ttk

class Main(tk.Frame):
    def __init__(self, master):
        tk.Frame.__init__(self, master)
        master.geometry('500x350')
        self.master = master
        self.tree = ttk.Treeview(self.master, height=15)
        self.tree.pack(fill='x')
        self.btn = tk.Button(master, text='click', command=self.clickbtn)
        self.btn.pack()
        self.aMenu = tk.Menu(master, tearoff=0)
        self.aMenu.add_command(label='Delete', command=self.delete)
        self.aMenu.add_command(label='Say Hello', command=self.hello)

        # attach popup to treeview widget
        self.tree.bind("<Button-3>", self.popup)

    def clickbtn(self):
        text = 'Hello ' + str(self.num)
        self.tree.insert('', 'end', text=text)
        self.num += 1

    def delete(self):
        print(self.tree.focus())
        if self.iid:
            self.tree.delete(self.iid)

    def hello(self):
        print ('hello!')

    def popup(self, event):
        self.iid = self.tree.identify_row(event.y)
        if self.iid:
            # mouse pointer over item
            self.tree.selection_set(self.iid)
            self.aMenu.post(event.x_root, event.y_root)            
        else:
            pass

Версия 2:

import tkinter as tk
from tkinter import ttk

class Main(tk.Frame):
    def __init__(self, master):
        master.geometry('500x350')
        self.master = master
        tk.Frame.__init__(self, master)
        self.tree = ttk.Treeview(self.master, height=15)
        self.tree.pack(fill='x')
        self.btn = tk.Button(master, text='click', command=self.clickbtn)
        self.btn.pack()
        self.rclick = RightClick(self.master)
        self.num = 0

        # attach popup to treeview widget
        self.tree.bind('<Button-3>', self.rclick.popup)
    def clickbtn(self):
        text = 'Hello ' + str(self.num)
        self.tree.insert('', 'end', text=text)
        self.num += 1

class RightClick:
    def __init__(self, master):

        # create a popup menu
        self.aMenu = tk.Menu(master, tearoff=0)
        self.aMenu.add_command(label='Delete', command=self.delete)
        self.aMenu.add_command(label='Say Hello', command=self.hello)

        self.tree_item = ''

    def delete(self):
        if self.tree_item:
            app.tree.delete(self.tree_item)

    def hello(self):
        print ('hello!')

    def popup(self, event):
        self.aMenu.post(event.x_root, event.y_root)
        self.tree_item = app.tree.focus()

root = tk.Tk()
app=Main(root)
root.mainloop()
1
ответ дан bzimor 19 August 2018 в 12:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: