Pythonのcanvasに表示した四角形を変形する
Pythonのtkinterのcanvasに四角形を表示して、それを変形させます。領域を選択するときによく使われる枠のようなものです。
目次
枠で領域を選択したい
ペイントのような画像を扱うアプリでは、矩形の領域を選択するときに画像上に枠を表示してガイドにするものが多いです。これができると便利そうですよね。
そこで、Pythonのtkinterのcanvasウィジェットに四角形(rectangle)を表示して、マウスに合わせてその形を変形させてみます。
どのようにするのか
マウスの左ボタンを押したときのポインタの座標を、枠(rectangle)の起点とします。
マウスをドラッグしているときのポインタの座標を、枠の終点とします。
ドラッグしたときに枠が表示されていなければ、起点と終点の座標を利用して新しい枠を作ります。もしすでに枠があるのであれば、枠の終点の座標を変更します。
枠(rectangle)を作ると、アイテムIDが振られます。そのIDを変数に格納しておきます。起動時と、枠を消したときには、その変数にNoneを入れます。こうすることで、アイテムIDの変数を参照すれば枠が存在するかどうかがわかります。
また、枠の座標を変更するには、canvasオブジェクトのcoordsメソッドを使用します。(coordsメソッドはアイテムの座標の取得もできます。)
tkinter.Canvas.coords(item, x0, y0, x1, y1)
x0, y0, x1, y1 = tkinter.Canvas.coords(item)
変数 |
型 |
内容 |
---|---|---|
item |
int |
アイテムID。 |
x0 |
int |
アイテムの左上端のx座標。 |
y0 |
int |
アイテムの左上端のy座標。 |
x1 |
int |
アイテムの右下端のx座標。 |
y1 |
int |
アイテムの右下端のy座標。 |
試してみた
import tkinter
import tkinter.ttk
class Application(tkinter.Frame):
CANVAS_WIDTH = 300
CANVAS_HEIGHT = 300
def __init__(self, master=None):
super().__init__(master)
self.master = master
self.master.title('tkinter canvas trial')
self.pack()
self.create_widgets()
self.startup()
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.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.select_all_button = tkinter.ttk.Button(self, text='Select All', command=self.select_all)
self.select_all_button.grid(row=5, column=1)
self.test_canvas = tkinter.Canvas(self, bg='lightblue',
width=self.CANVAS_WIDTH+1, height=self.CANVAS_HEIGHT+1,
highlightthickness=0)
self.test_canvas.grid(row=0, column=0, rowspan=6, padx=10, pady=10)
self.test_canvas.bind('<ButtonPress-1>', self.start_pickup)
self.test_canvas.bind('<B1-Motion>', self.pickup_position)
def startup(self):
self.rect_start_x = None
self.rect_start_y = None
self.rect = None
def start_pickup(self, event):
if 0 <= event.x <= self.CANVAS_WIDTH and 0 <= event.y <= self.CANVAS_HEIGHT:
self.start_x.set('x : ' + str(event.x))
self.start_y.set('y : ' + str(event.y))
self.rect_start_x = event.x
self.rect_start_y = event.y
def pickup_position(self, event):
if 0 <= event.x <= self.CANVAS_WIDTH and 0 <= event.y <= self.CANVAS_HEIGHT:
self.current_x.set('x : ' + str(event.x))
self.current_y.set('y : ' + str(event.y))
if self.rect:
self.test_canvas.coords(self.rect,
min(self.rect_start_x, event.x), min(self.rect_start_y, event.y),
max(self.rect_start_x, event.x), max(self.rect_start_y, event.y))
else:
self.rect = self.test_canvas.create_rectangle(self.rect_start_x,
self.rect_start_y, event.x, event.y, outline='red')
def select_all(self):
if self.rect:
self.test_canvas.coords(self.rect, 0, 0, self.CANVAS_WIDTH, self.CANVAS_HEIGHT)
else:
self.rect = self.test_canvas.create_rectangle(0, 0,
self.CANVAS_WIDTH, self.CANVAS_HEIGHT, outline='red')
x0, y0, x1, y1 = self.test_canvas.coords(self.rect)
self.start_x.set('x : ' + str(x0))
self.start_y.set('y : ' + str(y0))
self.current_x.set('x : ' + str(x1))
self.current_y.set('y : ' + str(y1))
root = tkinter.Tk()
app = Application(master=root)
app.mainloop()
コードの内容は上に書いたとおりですね。
実際に動かすとこうなります。
公開日
広告
PythonでGUIカテゴリの投稿
- PythonからWindowsのクリップボードに画像をコピーする
- PythonでCanvasをリサイズできるようにしてみた
- PythonでGUIに画像を表示する
- Pythonでクリップボードとのデータのやりとりをする
- Pythonでグラフ(Matplotlib)を表示して動的に変更する
- Pythonでディレクトリを選択するダイアログを使う
- Pythonでファイルを開くダイアログを使う
- Pythonで名前を付けて保存するダイアログを使う
- PythonのGUIを試してみた
- Pythonのcanvasにマウスで線を描いてみる
- Pythonのcanvasに表示した四角形を変形する
- Pythonのcanvasのマウスポインタの座標を取得する
- Pythonのtkinterのcanvasにクリップボードから画像をペーストする
- Pythonのtkinterのcanvasに表示する画像を切り替える