Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 渲染时间随时间增加_Python_Python 3.x_Tkinter_Tkinter Canvas - Fatal编程技术网

Python 渲染时间随时间增加

Python 渲染时间随时间增加,python,python-3.x,tkinter,tkinter-canvas,Python,Python 3.x,Tkinter,Tkinter Canvas,鉴于此代码 import tkinter canvas = tkinter.Canvas() canvas.pack() i = 0 k = 1 while True: canvas.create_text(100, 0+i, text="Python 3.6!", fill="red") canvas.update() canvas.create_rectangle(0, 0, canvas["width"], canvas["height"], fill=can

鉴于此代码

import tkinter

canvas = tkinter.Canvas()
canvas.pack()

i = 0
k = 1

while True:
    canvas.create_text(100, 0+i, text="Python 3.6!", fill="red")
    canvas.update()
    canvas.create_rectangle(0, 0, canvas["width"], canvas["height"], fill=canvas["background"])
    canvas.after(3)
    i = i + k

    if i==-1 or i==265:
        k = -k
我们可以看到,随着while循环的每一个循环,文本的移动都会减慢


现在,由于我们每秒多次重新渲染整个画布,难怪渲染速度很慢。然而,为什么它会随着时间的推移而变慢呢?这是因为大量的对象文本和矩形对象堆积在一起吗?这可以避免吗?

在每次迭代中,您都会创建一个新的文本项和一个矩形以隐藏上一个文本项,而不是移动文本,因此画布会变得拥挤,程序会变慢

有几种方法可以避免这种情况:

1) 删除文本,而不是将其隐藏在矩形后面:

   text = canvas.create_text(100, i, text="Python 3.6!", fill="red")
   ...
   canvas.delete(text)
2) 使用
coords
更改现有项目的坐标:

import tkinter

canvas = tkinter.Canvas()
canvas.pack()

i = 0
k = 1
text = canvas.create_text(100, i, text="Python 3.6!", fill="red")

while True:
    canvas.coords(text, 100, i)  # change coordinates of the text
    canvas.update()
    canvas.after(3)
    i = i + k
    if i==-1 or i==265:
        k = -k
3) 使用
移动
移动现有项目:

import tkinter

canvas = tkinter.Canvas()
canvas.pack()

i = 0
k = 1
text = canvas.create_text(100, i, text="Python 3.6!", fill="red")

while True:
    canvas.move(text, 0, k)  # increment by k the y coordinate of the text
    canvas.update()
    canvas.after(3)
    i = i + k
    if i==-1 or i==265:
        k = -k
最后,您还可以使用
after
方法制作动画,而不是while循环。比如:

import tkinter

root = tkinter.Tk()
canvas = tkinter.Canvas(root)
canvas.pack()

def motion(i, k):
    canvas.coords(text, 100, i)
    i = i + k
    if i==-1 or i==265:
        k = -k
    canvas.after(3, motion, i, k)

i = 0
k = 1
text = canvas.create_text(100, 0, text="Python 3.6!", fill="red")

motion(i, k)

root.mainloop()

不是移动文本,而是在每次迭代中创建一个新的文本项和一个矩形以隐藏上一个文本项,这样画布会变得拥挤,程序会变慢

有几种方法可以避免这种情况:

1) 删除文本,而不是将其隐藏在矩形后面:

   text = canvas.create_text(100, i, text="Python 3.6!", fill="red")
   ...
   canvas.delete(text)
2) 使用
coords
更改现有项目的坐标:

import tkinter

canvas = tkinter.Canvas()
canvas.pack()

i = 0
k = 1
text = canvas.create_text(100, i, text="Python 3.6!", fill="red")

while True:
    canvas.coords(text, 100, i)  # change coordinates of the text
    canvas.update()
    canvas.after(3)
    i = i + k
    if i==-1 or i==265:
        k = -k
3) 使用
移动
移动现有项目:

import tkinter

canvas = tkinter.Canvas()
canvas.pack()

i = 0
k = 1
text = canvas.create_text(100, i, text="Python 3.6!", fill="red")

while True:
    canvas.move(text, 0, k)  # increment by k the y coordinate of the text
    canvas.update()
    canvas.after(3)
    i = i + k
    if i==-1 or i==265:
        k = -k
最后,您还可以使用
after
方法制作动画,而不是while循环。比如:

import tkinter

root = tkinter.Tk()
canvas = tkinter.Canvas(root)
canvas.pack()

def motion(i, k):
    canvas.coords(text, 100, i)
    i = i + k
    if i==-1 or i==265:
        k = -k
    canvas.after(3, motion, i, k)

i = 0
k = 1
text = canvas.create_text(100, 0, text="Python 3.6!", fill="red")

motion(i, k)

root.mainloop()
琐事 你的怀疑是对的。重绘/渲染时间增加是因为通过堆叠对象(它们不会在每次迭代中消失,而是保留在内存中)泄漏内存,以及因为
tkinter
同时重绘所有对象。从这一点上说,我认为解决办法是明确的

答复 当然可以避免

有两种选择:

  • 如果您只需要设置一个对象的动画,那么您只需同时移动一个(并重新绘制一个)对象即可
  • 考虑这个例子:

    import tkinter as tk
    
    
    class App(tk.Tk):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
    
            self.canvas = tk.Canvas()
            self.canvas.pack()
            self.canvas.create_rectangle(0, 0, self.canvas["width"], self.canvas["height"], fill=self.canvas["background"])
            self.text = self.canvas.create_text(100, 1, text="Python 3.6!", fill="red")
            self.step = 3
            self.simulate_things()
    
        def simulate_things(self):
            if 0 <= self.canvas.coords(self.text)[1] + self.step <= self.canvas.winfo_height():
                # no need to change direction - still inside canvas
                pass
            else:
                # switch direction
                self.step *= -1
            
            # you can use coords method as alternative
            self.canvas.move(self.text, 0, self.step)
    
            # scheduling next move
            self.after(41, self.simulate_things)
    
    if __name__ == '__main__':
        app = App()
        app.mainloop()
    
    import tkinter as tk
    
    
    class App(tk.Tk):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
    
            self.canvas = tk.Canvas()
            self.canvas.pack()
            self.canvas.create_rectangle(0, 0, self.canvas["width"], self.canvas["height"], fill=self.canvas["background"])
            self.texts = {}
            self.i = 1
            self.step = 3
            self.simulate_things()
    
        def simulate_things(self):
            if self.i in self.texts:
                # hide previous object (if exists)
                self.canvas.itemconfigure(self.texts[self.i], state='hidden')
    
            if 0 <= self.i + self.step <= self.canvas.winfo_height():
                # no need to change direction - still inside canvas
                pass
            else:
                # switch direction
                self.step *= -1
            
            self.i += self.step
            
            if self.i in self.texts:
                # show hidden object for a step (if exists)
                self.canvas.itemconfigure(self.texts[self.i], state='normal')
            else:
                # or create a new one
                self.texts[self.i] = self.canvas.create_text(100, self.i, text="Python 3.6!", fill="red")
    
            # scheduling next move
            self.after(41, self.simulate_things)
    
    if __name__ == '__main__':
        app = App()
        app.mainloop()
    
    如您所见,管理性能的主要目标是减少重绘量(并将对象量保持在最小值)

    链接
    琐事 你的怀疑是对的。重绘/渲染时间增加是因为通过堆叠对象(它们不会在每次迭代中消失,而是保留在内存中)泄漏内存,以及因为
    tkinter
    同时重绘所有对象。从这一点上说,我认为解决办法是明确的

    答复 当然可以避免

    有两种选择:

  • 如果您只需要设置一个对象的动画,那么您只需同时移动一个(并重新绘制一个)对象即可
  • 考虑这个例子:

    import tkinter as tk
    
    
    class App(tk.Tk):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
    
            self.canvas = tk.Canvas()
            self.canvas.pack()
            self.canvas.create_rectangle(0, 0, self.canvas["width"], self.canvas["height"], fill=self.canvas["background"])
            self.text = self.canvas.create_text(100, 1, text="Python 3.6!", fill="red")
            self.step = 3
            self.simulate_things()
    
        def simulate_things(self):
            if 0 <= self.canvas.coords(self.text)[1] + self.step <= self.canvas.winfo_height():
                # no need to change direction - still inside canvas
                pass
            else:
                # switch direction
                self.step *= -1
            
            # you can use coords method as alternative
            self.canvas.move(self.text, 0, self.step)
    
            # scheduling next move
            self.after(41, self.simulate_things)
    
    if __name__ == '__main__':
        app = App()
        app.mainloop()
    
    import tkinter as tk
    
    
    class App(tk.Tk):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
    
            self.canvas = tk.Canvas()
            self.canvas.pack()
            self.canvas.create_rectangle(0, 0, self.canvas["width"], self.canvas["height"], fill=self.canvas["background"])
            self.texts = {}
            self.i = 1
            self.step = 3
            self.simulate_things()
    
        def simulate_things(self):
            if self.i in self.texts:
                # hide previous object (if exists)
                self.canvas.itemconfigure(self.texts[self.i], state='hidden')
    
            if 0 <= self.i + self.step <= self.canvas.winfo_height():
                # no need to change direction - still inside canvas
                pass
            else:
                # switch direction
                self.step *= -1
            
            self.i += self.step
            
            if self.i in self.texts:
                # show hidden object for a step (if exists)
                self.canvas.itemconfigure(self.texts[self.i], state='normal')
            else:
                # or create a new one
                self.texts[self.i] = self.canvas.create_text(100, self.i, text="Python 3.6!", fill="red")
    
            # scheduling next move
            self.after(41, self.simulate_things)
    
    if __name__ == '__main__':
        app = App()
        app.mainloop()
    
    如您所见,管理性能的主要目标是减少重绘量(并将对象量保持在最小值)

    链接

    您是在一般情况下提问,还是在您的示例中提问?这有点不清楚,因为首先你要说的是,这是一个“不足为奇的”。在那之后,你会在下一句中感到困惑。长话短说:是的,由于越来越多的对象被重新绘制,它影响了性能。是的,这是可以避免的。我想问一下我的怀疑是否正确,在这个例子中如何避免这种情况?你是在一般情况下还是在你的例子中问?这有点不清楚,因为首先你要说的是,这是一个“不足为奇的”。在那之后,你会在下一句中感到困惑。长话短说:是的,由于越来越多的对象被重新绘制,它影响了性能。是的,这是可以避免的。我想问一下我的怀疑是否正确,在这个例子中如何避免这种情况。谢谢你的解释!谢谢你的解释!非常感谢。实际上,我想知道如何避免
    while
    循环。你是一个真正的读心术者:谢谢!实际上,我想知道如何避免
    while
    循环。你是一个真正的读心术者:D