Pythonのcanvasにマウスで線を描いてみる
Pythonのtkinterのcanvasウィジェットに、マウスで線(絵)を描いてみます。
目次
どのようにして線を描くか
Pythonのtkinterモジュールのcanvasウィジェットに、マウスで線を描きます。
どのようにするかというと、 以前の投稿 のようにマウスをドラッグしたときのマウスポインタの座標を取得して、座標の取得毎に前の座標からの線を描いていきます。
意外と単純ですね。
Canvasウィジェットには描画されている内容をPostScriptで出力するメソッドがありますので、その機能を使ってPostScriptファイルに出力します。
試してみた
背景が白であることを前提に、黒で描くモードと消しゴムモード(白で描くモード)の切り替え用ラジオボタンが付いた簡単ペイントアプリを作ってみます。
import tkinter
from PIL import Image, ImageDraw
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()
self.setup()
def create_widgets(self):
self.vr = tkinter.IntVar()
self.vr.set(1)
self.write_radio = tkinter.Radiobutton(self, text='write', variable=self.vr, value=1, command=self.change_radio)
self.write_radio.grid(row=0, column=0)
self.erase_radio = tkinter.Radiobutton(self, text='erase', variable=self.vr, value=2, command=self.change_radio)
self.erase_radio.grid(row=0, column=1)
self.clear_button = tkinter.Button(self, text='clear all', command=self.clear_canvas)
self.clear_button.grid(row=0, column=2)
self.save_button = tkinter.Button(self, text='save', command=self.save_canvas)
self.save_button.grid(row=0, column=3)
self.test_canvas = tkinter.Canvas(self, bg='white', width=600, height=600)
self.test_canvas.grid(row=1, column=0, columnspan=4)
self.test_canvas.bind('<B1-Motion>', self.paint)
self.test_canvas.bind('<ButtonRelease-1>', self.reset)
def setup(self):
self.old_x = None
self.old_y = None
self.color = 'black'
self.eraser_on = False
self.im = Image.new('RGB', (600, 600), 'white')
self.draw = ImageDraw.Draw(self.im)
def change_radio(self):
if self.vr.get() == 1:
self.eraser_on = False
else:
self.eraser_on = True
def clear_canvas(self):
self.test_canvas.delete(tkinter.ALL)
def save_canvas(self):
self.test_canvas.postscript(file='out.ps', colormode='color')
def paint(self, event):
if self.eraser_on:
paint_color = 'white'
else:
paint_color = 'black'
if self.old_x and self.old_y:
self.test_canvas.create_line(self.old_x, self.old_y, event.x, event.y, width=5.0, fill=paint_color, capstyle=tkinter.ROUND, smooth=tkinter.TRUE, splinesteps=36)
self.draw.line((self.old_x, self.old_y, event.x, event.y), fill=paint_color, width=5)
self.old_x = event.x
self.old_y = event.y
def reset(self, event):
self.old_x, self.old_y = None, None
root = tkinter.Tk()
app = Application(master=root)
app.mainloop()
実際に描いているのは、paintという関数のところです。
Pillow.ImageDrawのイメージオブジェクトにも同時に描画していますが、これはCanvasウィジェットがPostScript出力しかできないからです。
PostScriptをPillowでレンダリングすることもできますが、その際にはPillowがGohstScriptを要求します。
というわけで、プログラム内部的に同時にイメージオブジェクトにも描画してしまって、加工や出力はイメージオブジェクトの方から行うわけです。
実際に動かしてみるとこうなります。
公開日
広告
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に表示する画像を切り替える