57262


Canvas上で右クリックメニューを表示したいのですが、右クリックイベントをBindし、座標を取得すると、Canvasウィジットの左上を（0,0）とした相対位置が取得されます。  
これに対して、tk.Menu.tk_popupに指定する座標は、親のウィンドウの左上を（0,0）とした相対位置のようです。

以下のコードでは、右クリックメニューが意図したところに表示されません。  
座標を適切にオフセットする必要があるようですが、方法が分かりません。  
ご存知の方がいらっしゃれば、ご教示をお願いします。

なお、キャンバスは縦横のスクロールバーを具備しており、実際のアプリケーションではキャンバス座標は座標上のアイテム位置に合わせてサイズが可変としています。

[code]

    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()
    
    
[/code]


CC BY-SA 4.0
2019-08-09T01:26:56.910
57261
2019-08-09T02:41:06.950
32891
question
python3 tkinter
Python tk.Canvas上で右クリック座標にtk_popupを正しく表示したい


座標を適切にオフセットするには`x`,`y`ではなく`x_root`,`y_root`を使います。

**変更箇所**

[code]

       #self.popup_menu.tk_popup(int(event.x),int(event.y),0)  #変更前
        self.popup_menu.tk_popup(event.x_root,event.y_root,0)
    
[/code]

[effbot.orgのtkinter-events-and-
bindings](https://effbot.org/tkinterbook/tkinter-events-and-
bindings.htm)からクリックイベントのリファレンスを抜粋します。

> x, y  
>  The current mouse position, in pixels.  
>  x_root, y_root  
>  The current mouse position relative to the upper left corner of the screen,
> in pixels.


CC BY-SA 4.0
2019-08-09T02:41:06.950
57262
2019-08-09T02:41:06.950
9820
57261
answer