テキスト修正
「いちばんやさしいPython入門教室」1で演習をすすめてきました.このテキストはひとつひとつのcodeがどのような考え方でそこにあるのかを丁寧に解説してくれています.なので,coding初心者がcodingを理解するために,じっくり読むのにはとてもいいテキストです.ただ,論理の流れを重視しているためか,すこしcodingの常識からずれているところがあります.その修正です.
example07-08-01.pyの修正(tag版)
このあたりのコード,まずいです.
長くやったり,たくさんやったりしたらもたもたしてきます.はじめは,cpuとかのせいかとおもってあきらめてたんですが,あまりに遅くって...
修正のアイデアはどっかにあったんですが,もうだいぶむかしに修正しちゃったのでなにが原典だったかわかりません. -タグとバインドが最初のアイデアとしては同じです.
問題は,
canvas.create_oval(self.x - 20, self.y - 20,
self.x + 20, self.y + 20, fill="white", width=0)
です.'white'で上書きして,消しています.これはcodeで絵をかくときの常とう手段です.画面全体をpictとして管理して書いていくときには効率がいいんです.でも,objectに対して,これをやるとobjectがどんどん増殖します.結果として必要なメモリーが増えて,描画がもたもたしてくるんです.たぶん
なんで正しくはobjectをdeleteします.
まず,create_ovalで識別のためにtagをつけて生成します.
canvas.create_oval(self.x - 20, self.y - 20,
self.x + 20, self.y + 20,
fill=self.color, width=0,
tag=self.color)
それを=white=で上書きする代わりに,つぎのようにしてdeleteします.
canvas.delete(self.color)
これで試してみてください.とっても速くなるはずです.
ただ,windowsでは形がいびつな感じがするかもしれません.これは,描画ライブラリのせいのようです2.mac版ではばっちりです.
さらに正統派(obj版)
さらにobjectを消すという考え方の方がわざわざtagで識別するより筋が良さそうです. -https://pythonprogramming.altervista.org/delete-an-object-on-the-canvas/?doing_wp_cron=1591052096.4730188846588134765625
基本的には,
canvas.delete(self.ball)
... 中略 ...
self.ball = canvas.create_oval(self.x - 20, self.y - 20,
self.x + 20, self.y + 20,
fill=self.color, width=0)
としてself.ballというobjectにしてしまって,それを,deleteするだけです.でも,元テキストからはcodeの順番を相当いじる必要があります.
完成形をつけておきますので,時間のある人は,どこがどうなっているか,なんでか悩んで見てください.順番は,
- 上のように修正してみる 2.
self.ballがないと怒られるので,initでnoneしておく 3.canvasがないと怒られるので,ballsを生成する前に持っていく です.
import tkinter as tk
speed = 10
class Ball:
global speed
def __init__(self, x, y, dx, dy, color):
self.x = x
self.y = y
self.dx = dx
self.dy = dy
self.color = color
self.ball = None
def test(self):
print(self.x)
print(self.y)
def move(self, canvas):
canvas.delete(self.ball)
self.x = self.x + self.dx
self.y = self.y + self.dy
self.ball = canvas.create_oval(self.x - 20, self.y - 20,
self.x + 20, self.y + 20,
fill=self.color, width=0)
if self.x >= canvas.winfo_width():
self.dx = -speed
if self.x < 0:
self.dx = +speed
if self.y >= canvas.winfo_height():
self.dy = -speed
if self.y < 0:
self.dy = +speed
root = tk.Tk()
root.geometry("600x400")
canvas = tk.Canvas(root, width=600, height=400, bg="white")
canvas.place(x=0, y=0)
balls = [
Ball(300, 400, 1, 1, "red"),
Ball(200, 400, 2, 1, "green"),
Ball(300, 200, 1, 2, "blue")
]
def loop():
for b in balls:
b.move(canvas)
root.after(10, loop)
root.after(10, loop)
root.mainloop()
Footnotes
1 「いちばんやさしいPython入門教室」大澤文孝著,(ソーテック社出版,2017).
2 (2020/06/16追記)バックを黒くして,ボールを明るくするとうまく出ます.人間の目のせいでしょうか..
- source ~/Desktop/lecture_21s/CompAInfo/tmp.org