HOME | 9. ボードゲーム用 GUI を作ろう | Python | 11. Canvas を使って納涼しよう | download | 書き込む |
[code 1] Tk.Canvas を作る部分
01: def __init__(self, master=None): 02: Tk.Frame.__init__(self, master) 03: self.master.title("Toy") 04: self.master.geometry("+20+20") 05: self.cvs = Tk.Canvas(self, scrollregion=("0c", "0c", "40c", "40c"), width="20c", height="20c", 06: relief=Tk.SUNKEN, borderwidth=2, bg='#FFEFD5') 07: self.cvs.grid(row=0, column=0, sticky= Tk.N+Tk.E+Tk.W+Tk.S) 08: 09: xscroll = Tk.Scrollbar(self, orient=Tk.HORIZONTAL, command=self.cvs.xview) 10: xscroll.grid(row=1, column=0, sticky=Tk.E+Tk.W) 11: 12: yscroll = Tk.Scrollbar(self, orient=Tk.VERTICAL, command=self.cvs.yview) 13: yscroll.grid(row=0, column=1, sticky=Tk.N+Tk.S) 14: 15: self.cvs.config(xscrollcommand=xscroll.set, yscrollcommand=yscroll.set) 16: self.grid_rowconfigure(0, weight=1, minsize=0) 17: self.grid_columnconfigure(0, weight=1, minsize=0)[code 2] Frame を pack する部分
01: if __name__ == '__main__': 02: f = Frame() 03: f.pack(fill=Tk.BOTH, expand=1) 04: f.mainloop()
(a) | (b) |
(c) | (d) |
図1:
a) 色分けして箱にしまう課題(左上)
b) 正三角形を大きさ順に並べる課題(右上)
c) 番号を線で結ぶ課題(左下)
d) しりとりになるように単語を線で結ぶ課題(右下)
刺激に反応するオブジェクトを表すのには新しいクラスを定義するのが OOP の定石です。
ここでもそれに従って class CanvasItem を定義します。
CanvasItem の定義は以下の通りです。
[code 3]
01: class CanvasItem: 02: canvas = None 03: 04: def make_binds(self): 05: CanvasItem.canvas.tag_bind(self.id, '<1>', self.drag_start) 06: CanvasItem.canvas.tag_bind(self.id, '<Button1-Motion>', self.dragging) 07: 08: def drag_start(self, event): 09: self.x = event.x 10: self.y = event.y 11: 12: def dragging(self, event): 13: x1 = event.x 14: y1 = event.y 15: CanvasItem.canvas.move(self.id, x1-self.x, y1-self.y) 16: self.x = x1 17: self.y = y1
[code 4]
01: class CanvasOval(CanvasItem): 02: def __init__(self, x0, y0, x1, y1, **key): 03: self.id = CanvasItem.canvas.create_oval(x0, y0, x1, y1, **key) 04: self.make_binds() 05: 06: class CanvasRectangle(CanvasItem): 07: def __init__(self, x0, y0, x1, y1, **key): 08: self.id = CanvasItem.canvas.create_rectangle(x0, y0, x1, y1, **key) 09: self.make_binds() 10: 11: class CanvasTriangle(CanvasItem): 12: def __init__(self, x, y, r, color): 13: self.id = CanvasItem.canvas.create_polygon(str(x)+'c', str(y-r*SQRT3)+'c', str(x-r)+'c', str(y)+'c', 14: str(x+r)+'c', str(y)+'c', fill=color) 15: self.make_binds() 16: 17: class CanvasText(CanvasItem): 18: def __init__(self, *pos, **key): 19: self.id = CanvasItem.canvas.create_text(*pos, **key) 20: self.make_binds() 21: 22: 23: class CanvasCircleNumber(CanvasItem): 24: def __init__(self, x, y, num, session): 25: s = session + str(num) 26: self.circle = CanvasItem.canvas.create_oval('%fc' % (x-0.7), '%fc' % (y-0.7), '%fc' % (x+0.7), '%fc' % (y+0.7), 27: width=2, outline='red', fill='#FFFFF0', tag=s) 28: self.number = CanvasItem.canvas.create_text(str(x)+'c', str(y)+'c', text=str(num), 29: font=('Helvetica', '14', 'bold'), tag=s) 30: CanvasItem.canvas.tag_bind(s, '<1>', self.drag_start) 31: CanvasItem.canvas.tag_bind(s, '<Button1-Motion>', self.dragging) 32: 33: def dragging(self, event): 34: x1 = event.x 35: y1 = event.y 36: CanvasItem.canvas.move(self.circle, x1-self.x, y1-self.y) 37: CanvasItem.canvas.move(self.number, x1-self.x, y1-self.y) 38: self.x = x1 39: self.y = y1
[code 5]
01: #! /usr/bin/env python 02: # -*- coding: shift_jis -*- 03: """ 04: toy.py 05: 06: July 08, 2005 07: """ 08: import Tkinter as Tk 09: import random as R 10: import math 11: 12: 13: 14: TITLE_COLOER = '#FF6600' 15: COLOR = ['red', 'gold', 'blue'] 16: TITLE_FONT = ('Helvetica', '20', 'bold') 17: CAPPING = [u'あさがお', u'おけ', u'けいと', u'とり', u'リス', u'スイカ', u'かき', u'きもの', u'のはら'] 18: SQRT3 = math.sqrt(3) 19: 20: 21: class CanvasItem: 22: canvas = None 23: 24: def make_binds(self): 25: CanvasItem.canvas.tag_bind(self.id, '<1>', self.drag_start) 26: CanvasItem.canvas.tag_bind(self.id, '<Button1-Motion>', self.dragging) 27: 28: def drag_start(self, event): 29: self.x = event.x 30: self.y = event.y 31: 32: def dragging(self, event): 33: x1 = event.x 34: y1 = event.y 35: CanvasItem.canvas.move(self.id, x1-self.x, y1-self.y) 36: self.x = x1 37: self.y = y1 38: 39: 40: class CanvasOval(CanvasItem): 41: def __init__(self, x0, y0, x1, y1, **key): 42: self.id = CanvasItem.canvas.create_oval(x0, y0, x1, y1, **key) 43: self.make_binds() 44: 45: class CanvasRectangle(CanvasItem): 46: def __init__(self, x0, y0, x1, y1, **key): 47: self.id = CanvasItem.canvas.create_rectangle(x0, y0, x1, y1, **key) 48: self.make_binds() 49: 50: class CanvasTriangle(CanvasItem): 51: def __init__(self, x, y, r, color): 52: self.id = CanvasItem.canvas.create_polygon(str(x)+'c', str(y-r*SQRT3)+'c', str(x-r)+'c', str(y)+'c', 53: str(x+r)+'c', str(y)+'c', fill=color) 54: self.make_binds() 55: 56: class CanvasText(CanvasItem): 57: def __init__(self, *pos, **key): 58: self.id = CanvasItem.canvas.create_text(*pos, **key) 59: self.make_binds() 60: 61: 62: class CanvasCircleNumber(CanvasItem): 63: def __init__(self, x, y, num, session): 64: s = session + str(num) 65: self.circle = CanvasItem.canvas.create_oval('%fc' % (x-0.7), '%fc' % (y-0.7), '%fc' % (x+0.7), '%fc' % (y+0.7), 66: width=2, outline='red', fill='#FFFFF0', tag=s) 67: self.number = CanvasItem.canvas.create_text(str(x)+'c', str(y)+'c', text=str(num), 68: font=('Helvetica', '14', 'bold'), tag=s) 69: CanvasItem.canvas.tag_bind(s, '<1>', self.drag_start) 70: CanvasItem.canvas.tag_bind(s, '<Button1-Motion>', self.dragging) 71: 72: def dragging(self, event): 73: x1 = event.x 74: y1 = event.y 75: CanvasItem.canvas.move(self.circle, x1-self.x, y1-self.y) 76: CanvasItem.canvas.move(self.number, x1-self.x, y1-self.y) 77: self.x = x1 78: self.y = y1 79: 80: 81: 82: 83: class Frame (Tk.Frame): 84: 85: def __init__(self, master=None): 86: Tk.Frame.__init__(self, master) 87: self.master.title("Toy") 88: self.master.geometry("+20+20") 89: self.cvs = Tk.Canvas(self, scrollregion=("0c", "0c", "40c", "40c"), width="20c", height="20c", 90: relief=Tk.SUNKEN, borderwidth=2, bg='#FFEFD5') 91: self.cvs.grid(row=0, column=0, sticky= Tk.N+Tk.E+Tk.W+Tk.S) 92: 93: xscroll = Tk.Scrollbar(self, orient=Tk.HORIZONTAL, command=self.cvs.xview) 94: xscroll.grid(row=1, column=0, sticky=Tk.E+Tk.W) 95: 96: yscroll = Tk.Scrollbar(self, orient=Tk.VERTICAL, command=self.cvs.yview) 97: yscroll.grid(row=0, column=1, sticky=Tk.N+Tk.S) 98: 99: self.cvs.config(xscrollcommand=xscroll.set, yscrollcommand=yscroll.set) 100: self.grid_rowconfigure(0, weight=1, minsize=0) 101: self.grid_columnconfigure(0, weight=1, minsize=0) 102: 103: # assign a CanvasItem class parameter 104: CanvasItem.canvas=self.cvs 105: 106: # binding 107: self.cvs.bind('<3>', self.draw_start) 108: self.cvs.bind('<Button3-Motion>', self.drawing) 109: self.cvs.bind('<Double-Button-1>', self.delete_line) 110: 111: 112: # Display a 2x2 rectangular grid. 113: self.cvs.create_line('0c', '20c', '40c', '20c', width=2) 114: self.cvs.create_line('20c', '0c', '20c', '40c', width=2) 115: 116: 117: # First Toy 118: self.cvs.create_text('10c', '1.5c', text=u'色別に整理して、しまいましょう。\n左ボタンドラッグで動きます。', 119: font=TITLE_FONT, fill=TITLE_COLOER) 120: for i, c in enumerate(COLOR): 121: self.cvs.create_line('%dc' % (i*6+1), '16c', '%dc' % (i*6+1), '19c', '%dc' % (i*6+6), 122: '19c', '%dc' % (i*6+6), '16c', fill=c, width=3) 123: 124: for i in range(5): 125: x=R.randint(200, 1800) * 0.01 126: y=R.randint(300, 1500) * 0.01 127: r=R.randint(30, 150) * 0.01 128: c=R.randint(0,2) 129: CanvasOval('%fc' % (x-r), '%fc' % (y-r), '%fc' % (x+r), '%fc' % (y+r), fill=COLOR[c], width=0) 130: 131: for i in range(5): 132: x=R.randint(100, 1700) * 0.01 133: y=R.randint(300, 1500) * 0.01 134: w=R.randint(50, 150) * 0.01 135: h=R.randint(50, 150) * 0.01 136: c=R.randint(0,2) 137: CanvasRectangle('%fc' % (x), '%fc' % (y), '%fc' % (x+w), '%fc' % (y+h), fill=COLOR[c], width=0) 138: 139: 140: # Second Toy 141: self.cvs.create_text('30c', '1.5c', text=u'三角形を大きい順に並べましょう。\n左ボタンドラッグで動きます。', 142: font=TITLE_FONT, fill=TITLE_COLOER) 143: for i in range(10): 144: x=R.randint(2200, 3800) * 0.01 145: y=R.randint( 300, 1950) * 0.01 146: r=R.randint(3000, 20000) * 0.0001 147: c=R.randint(0,2) 148: CanvasTriangle(x, y, r, COLOR[c]) 149: 150: # Third Toy 151: self.cvs.create_text('10c', '21.5c', text=u'数字を順番に線で結びましょう。\n右ボタンドラッグで線が引けます。', 152: font=TITLE_FONT, fill=TITLE_COLOER) 153: self.cvs.create_text('10c', '22.8c', text=u'数字が重なっていたら、ドラッグして位置を少しずらしましょう。', 154: font=('Helveticla', '12')) 155: for i in range(12): 156: x=R.randint(200, 1800) * 0.01 157: y=R.randint(2400, 3600) * 0.01 158: CanvasCircleNumber(x, y, i+1, 'third') 159: 160: 161: # Fourth Toy 162: self.cvs.create_text('30c', '21.5c', text=u'「しりとり」になるように単語を線で結びましょう。\n' 163: u'右ボタンドラッグで線が引けます。', 164: font=TITLE_FONT, fill=TITLE_COLOER) 165: self.cvs.create_text('30c', '22.8c', text=u'単語が重なっていたら、ドラッグして位置を少しずらしましょう。', 166: font=('Helveticla', '12')) 167: 168: 169: for txt in CAPPING: 170: x=R.randint(2200, 3800) * 0.01 171: y=R.randint(2400, 3600) * 0.01 172: r=R.randint(0,200) 173: g=R.randint(0,200) 174: b=R.randint(0,200) 175: CanvasText(str(x)+'c', str(y)+'c', text=txt, font=('Helvetica', '18', 'bold'), fill='#%02X%02X%02X' % (r, g, b)) 176: 177: 178: 179: 180: ### 181: def draw_start(self, event): 182: self.x = self.cvs.canvasx(event.x, '0.2m') 183: self.y = self.cvs.canvasy(event.y, '0.2m') 184: 185: def drawing(self, event): 186: x1 = self.cvs.canvasx(event.x, '0.2m') 187: y1 = self.cvs.canvasy(event.y, '0.2m') 188: self.cvs.create_line(self.x, self.y, x1, y1, width=2, fill='#CC3300', tag='line') 189: self.x = x1 190: self.y = y1 191: 192: def delete_line(self, event): 193: self.cvs.delete('line') 194: 195: 196: 197: ##----------------------------------------------------- 198: if __name__ == '__main__': 199: f = Frame() 200: f.pack(fill=Tk.BOTH, expand=1) 201: f.mainloop()
HOME | 9. ボードゲーム用 GUI を作ろう | Python | 11. Canvas を使って納涼しよう | download | 書き込む |