Pythonのcanvasのマウスポインタの座標を取得する

Pythonのtkinterのcanvas上で、マウスのポインタの座標を取得してみます。

目次

  1. マウスの位置はイベントで取得する
  2. 実施例
  3. 注意点

マウスの位置はイベントで取得する

PythonのGUIモジュールのtkinterのcanvasで、マウスの位置を座標で取得します。

canvasオブジェクトにバインドしたマウスイベントで実行される関数に、引数としてeventが渡されます。そのeventのプロパティxがx座標を、プロパティyがy座標を表します。

マウスのイベントについては、 こちらのサイト に詳しく書かれています。

実施例

試してみましょう。

300x300のサイズのcanvasでマウスの左ボタンを押したときの座標を取得してlabelに表示します。

import tkinter
import tkinter.ttk

class Application(tkinter.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.master = master
        self.master.title('tkinter canvas trial')
        self.pack()
        self.create_widgets()

    def create_widgets(self):
        self.start_x = tkinter.StringVar()
        self.start_y = tkinter.StringVar()
        self.current_x = tkinter.StringVar()
        self.current_y = tkinter.StringVar()
        self.stop_x = tkinter.StringVar()
        self.stop_y = tkinter.StringVar()

        self.label_description = tkinter.ttk.Label(self, text='Mouse position')
        self.label_description.grid(row=0, column=1)
        self.label_start_x = tkinter.ttk.Label(self, textvariable=self.start_x)
        self.label_start_x.grid(row=1, column=1)
        self.label_start_y = tkinter.ttk.Label(self, textvariable=self.start_y)
        self.label_start_y.grid(row=2, column=1)
        self.label_current_x = tkinter.ttk.Label(self, textvariable=self.current_x)
        self.label_current_x.grid(row=3, column=1)
        self.label_current_y = tkinter.ttk.Label(self, textvariable=self.current_y)
        self.label_current_y.grid(row=4, column=1)
        self.label_stop_x = tkinter.ttk.Label(self, textvariable=self.stop_x)
        self.label_stop_x.grid(row=5, column=1)
        self.label_stop_y = tkinter.ttk.Label(self, textvariable=self.stop_y)
        self.label_stop_y.grid(row=6, column=1)

        self.test_canvas = tkinter.Canvas(self, bg='lightblue', width=300, height=300, highlightthickness=0)
        self.test_canvas.grid(row=0, column=0, rowspan=7)
        self.test_canvas.bind('<ButtonPress-1>', self.start_pickup)
        self.test_canvas.bind('<B1-Motion>', self.pickup_position)
        self.test_canvas.bind('<ButtonRelease-1>', self.stop_pickup)

    def start_pickup(self, event):
        self.start_x.set('x : ' + str(event.x))
        self.start_y.set('y : ' + str(event.y))
        self.stop_x.set('')
        self.stop_y.set('')

    def pickup_position(self, event):
        self.current_x.set('x : ' + str(event.x))
        self.current_y.set('y : ' + str(event.y))

    def stop_pickup(self, event):
        self.stop_x.set('x : ' + str(event.x))
        self.stop_y.set('y : ' + str(event.y))

root = tkinter.Tk()
app = Application(master=root)
app.mainloop()

ラベルをたくさん並べているのでコードは長いですが、仕組みは単純ですね。

canvasにイベントが3つバインドされています。それぞれ下記のようなイベントです。

  • <ButtonPress-1>は左ボタンが押されたとき。
  • <B1-Motion>は左ボタンを押しながら動かしたとき。(ドラッグ)
  • <ButtonRelease-1>は左ボタンを離したとき。(ドロップ)

それぞれバインドした関数が呼び出されると、その関数内でeventを参照して座標を取得し、labelの更新用の変数にセットしています。

あとは自動的にラベルの中身が更新されるわけですね。

実際に動かしてみるとこうなります。

canvasの左上端が0, 0で右下端が300, 300になっているのですね。

注意点

実行例を見てアレっとなったのですが、canvasの外側の領域でもマウスポインタの座標を拾っています。数字がマイナスになったり、300より大きくなったりしてますね。

実用するときはcanvas内かどうかの判定が必要そうです。

広告

PythonでGUIカテゴリの投稿