私は、いくつかの機能を追加する方法を見つけようとしている python-tkinter GUI アプリを持っています。アプリのリストボックス領域のアイテムを右クリックして、コンテキスト メニューを表示する方法があることを期待していました。tkinter はこれを達成できますか? gtk やその他の gui ツールキットを調べた方がよいでしょうか?
4 に答える
Menuインスタンスを作成し、
そのpost()
またはtk_popup()
メソッド を呼び出す関数を記述します。
tkinterのドキュメントには、現在、に関する情報はありませんtk_popup()
。説明またはソースについては、 Tkのドキュメント
を
お読みください。
::tk_popup- この手順では、メニューがポップアップ表示され、トラバースするように設定されます メニューとそのサブメニュー。 引数: menu-ポップアップするメニューの名前。 x、y-メニューをポップアップするルート座標。 entry-(x、y)を中心とするメニューエントリのインデックス。 省略または{}として指定した場合、メニューの 左上隅は(x、y)になります。
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)
。
ただし、右クリックに関連付けられている数は、すべてのプラットフォームで同じではありません。
ダーウィン/アクアでは、左から右へのボタンは1,3,2です。 Xサーバーとして最近のXQuartzを使用するDarwin/X11では、それらは1,2,3です。 他のXサーバーは異なる場合があります。
リストボックスにコンテキストメニューを追加する私が書いた例を次に示します。
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()
の使用は、effbotの例でgrab_release()
観察されました。
その効果は、すべてのシステムで同じではない場合があります。
需要を調整するために、上記の conext メニュー コードにいくつかの変更を加えました。共有すると役立つと思います。
バージョン 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)
self.num = 0
# 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
root = tk.Tk()
app=Main(root)
root.mainloop()
バージョン 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()
重要な警告:
(座標を含むイベント引数が「event」と呼ばれると仮定します): 「event.x_root」と「event.y_root」を引数として使用しない限り、tk_popup(...) を呼び出しても何も起こらないか、または表示されません。「event.x」と「event.y」を使用するという明白な方法を実行すると、座標の名前が「x」と「y」であり、「x_root」と「x_root」の言及がないにもかかわらず、機能しません。 「y_root」はその中のどこかに。
grab_release(..) に関しては、どこでも必要ありません。"tearoff=0" も必要ありません。1 に設定すると (デフォルト)、コンテキスト メニューに点線のエントリが追加されます。クリックすると、コンテキスト メニューが切り離され、ウィンドウ デコレータを備えた独自のトップレベル ウィンドウになります。teaoff=0 は、このエントリを非表示にします。さらに、メニューのマスターを特定のウィジェットまたはルートに設定するかどうかは問題ではありません。