Python tk.Canvas上で右クリック座標にtk_popupを正しく表示したい
Canvas上で右クリックメニューを表示したいのですが、右クリックイベントをBindし、座標を取得すると、Canvasウィジットの左上を(0,0)とした相対位置が取得されます。
これに対して、tk.Menu.tk_popupに指定する座標は、親のウィンドウの左上を(0,0)とした相対位置のようです。
以下のコードでは、右クリックメニューが意図したところに表示されません。
座標を適切にオフセットする必要があるようですが、方法が分かりません。
ご存知の方がいらっしゃれば、ご教示をお願いします。
なお、キャンバスは縦横のスクロールバーを具備しており、実際のアプリケーションではキャンバス座標は座標上のアイテム位置に合わせてサイズが可変としています。
import tkinter as tk
from tkinter import ttk
class MainWindow():
def __init__(self):
self.main_window = tk.Tk()
geo_string = '600x400+0+0'
_InFrame_Btn_ = tk.LabelFrame(
self.main_window,
text = 'ButtonFrame'
)
_InFrame_Canvas_ = tk.LabelFrame(
self.main_window,
text = 'CanvasFrame'
)
_BtnDummy_01 = tk.Button(
_InFrame_Btn_,
text = 'Dummy'
)
_BtnDummy_02 = tk.Button(
_InFrame_Btn_,
text = 'Dummy'
)
_BtnDummy_03 = tk.Button(
_InFrame_Btn_,
text = 'Dummy'
)
_BtnDummy_04 = tk.Button(
_InFrame_Btn_,
text = 'Dummy'
)
self._Canvas_ = tk.Canvas(
_InFrame_Canvas_,
background = 'white'
)
self.canvas_h_scroll = ttk.Scrollbar(
_InFrame_Canvas_,
orient = tk.HORIZONTAL,
command = self._Canvas_.xview
)
self.canvas_v_scroll = ttk.Scrollbar(
_InFrame_Canvas_,
orient = tk.VERTICAL,
command = self._Canvas_.yview
)
self._Canvas_['xscrollcommand'] = self.canvas_h_scroll.set
self._Canvas_['yscrollcommand'] = self.canvas_v_scroll.set
self._Canvas_['scrollregion'] = (-100,-100,800,600)
#_InFrame_Btn_
_BtnDummy_01.pack(side=tk.LEFT)
_BtnDummy_02.pack(side=tk.RIGHT)
_BtnDummy_03.pack(side=tk.TOP)
_BtnDummy_04.pack(side=tk.TOP)
#_InFrame_Canvas_
self.canvas_h_scroll.grid(row=1, column=0, sticky=tk.E+tk.W)
self.canvas_v_scroll.grid(row=0, column=1, sticky=tk.N+tk.S)
self._Canvas_.grid(row=0, column=0, sticky=tk.N+tk.E+tk.W+tk.S)
_InFrame_Btn_.pack(side=tk.TOP,fill=tk.X)
_InFrame_Canvas_.pack(side=tk.BOTTOM,fill=tk.X)
# Mouse Right-Button Single Click Event
self._Canvas_.bind('<Button-3>',self.mouse_right_click_on_canvas)
self.main_window.title('PopupMenuTest')
self.main_window.geometry(geo_string)
self.main_window.mainloop()
return
def mouse_right_click_on_canvas(self, event):
x = self._Canvas_.canvasx(event.x)
y = self._Canvas_.canvasy(event.y)
self.popup_menu = tk.Menu(self._Canvas_, tearoff = 0)
self.popup_menu.add_command(label = 'new')
self.popup_menu.add_separator()
self.popup_menu.add_command(label = 'update')
self.popup_menu.tk_popup(int(event.x),int(event.y),0)
if __name__ == '__main__':
gui = MainWindow()