Ответ 1
Вы должны создать экземпляр 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 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.
Вот пример, который я написал, который добавляет контекстное меню в список:
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.
Его эффект не может быть одинаковым для всех систем.