需调试bug

tkinter 创建的屏保

  • bug : 程序提示小球移动时最大递归深度超过限制
import random
import tkinter


class RandomBoll:
    def __init__(self, canvas, screen_width, screen_height):

        self.screenwidth = screen_width
        self.screenheight = screen_height
        self.canvas = canvas

        self.xPos = random.randint(10, int(self.screenwidth - 20))
        self.yPos = random.randint(10, int(self.screenheight - 20))
        self.xSpeed = random.randint(4, 20)
        self.ySpeed = random.randint(4, 20)
        self.radios = random.randint(20, 120)
        self.color = '#%02x%02x%02x' % (random.randint(0, 255),
                                        random.randint(0, 255),
                                        random.randint(0, 255))

    def create_ball(self):
        x1 = self.xPos - self.radios
        y1 = self.yPos - self.radios
        x2 = self.xPos + self.radios
        y2 = self.yPos + self.radios

        self.item = self.canvas.create_oval(x1, y1,
                                            x2, y2,
                                            fill=self.color,
                                            outline=self.color)

    def move_ball(self):
        self.xPos += self.xSpeed
        self.yPos += self.ySpeed

        if self.xPos + self.radios >= self.screenwidth or self.xPos < self.radios:
            self.xSpeed = -self.xSpeed
        if self.yPos + self.radios >= self.screenheight or self.yPos < self.radios:
            self.ySpeed *= -1

        self.canvas.move(self.item, self.xSpeed, self.ySpeed)


class ScreenSaver:
    balls = list()

    def __init__(self):
        self.numBalls = random.randint(6, 20)
        self.root = tkinter.Tk()
        self.root.overrideredirect(1)
        self.root.bind('<Motion>', self.my_quit)
        w, h = self.root.winfo_screenwidth(), self.root.winfo_screenheight()
        self.canvas = tkinter.Canvas(self.root, width=w, height=h)
        self.canvas.pack()

        for i in range(self.numBalls):
            ball = RandomBoll(self.canvas, screen_width=w, screen_height=h)
            ball.create_ball()
            self.balls.append(ball)

        self.run_screen_saver()
        self.root.mainloop()

    def run_screen_saver(self):
        for ball in self.balls:
            ball.move_ball()
        self.canvas.after(200, self.run_screen_saver())

    def my_quit(self, e):
        self.root.destroy()


if __name__ == '__main__':
    ScreenSaver()

代码调试报错:

C:\Users\Administrator\AppData\Local\Programs\Python\Python37\python3.7.exe E:/Python_work/ziqizhan/ScreenSaver.py
Traceback (most recent call last):
  File "E:/Python_work/ziqizhan/ScreenSaver.py", line 74, in <module>
    ss = ScreenSaver()
  File "E:/Python_work/ziqizhan/ScreenSaver.py", line 61, in __init__
    self.run_screen_saver()
  File "E:/Python_work/ziqizhan/ScreenSaver.py", line 67, in run_screen_saver
    self.canvas.after(200, self.run_screen_saver())
  File "E:/Python_work/ziqizhan/ScreenSaver.py", line 67, in run_screen_saver
    self.canvas.after(200, self.run_screen_saver())
  File "E:/Python_work/ziqizhan/ScreenSaver.py", line 67, in run_screen_saver
    self.canvas.after(200, self.run_screen_saver())
  [Previous line repeated 991 more times]
  File "E:/Python_work/ziqizhan/ScreenSaver.py", line 66, in run_screen_saver
    ball.move_ball()
  File "E:/Python_work/ziqizhan/ScreenSaver.py", line 41, in move_ball
    self.canvas.move(self.item, self.xSpeed, self.ySpeed)
  File "C:\Users\Administrator\AppData\Local\Programs\Python\Python37\lib\tkinter\__init__.py", line 2591, in move
    self.tk.call((self._w, 'move') + args)
RecursionError: maximum recursion depth exceeded while calling a Python object

Process finished with exit code 1
  • 问题原因:
    第67行传递的参数为
self.canvas.after(200, self.run_screen_saver())

该局语句的含义为:200毫秒之后开始调用函数run_screen_saver方法,而并非将run
_screen_saver的函数地址传递给函数after

    def after(self, ms, func=None, *args):
        """Call function once after given time.

        MS specifies the time in milliseconds. FUNC gives the
        function which shall be called. Additional parameters
        are given as parameters to the function call.  Return
        identifier to cancel scheduling with after_cancel."""
        if not func:
            # I'd rather use time.sleep(ms*0.001)
            self.tk.call('after', ms)
            return None

after函数中缺失存在 if not func 就开始调用self.tk.call,与报错信息相符合,在学习中应该注意函数作为参数传入,和直接调用函数的区别。
纠正后参数为:

self.canvas.after(200, self.run_screen_saver)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值