Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/348.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 锯齿形tkinter主循环帧持续时间?_Python_Tkinter_Python Imaging Library - Fatal编程技术网

Python 锯齿形tkinter主循环帧持续时间?

Python 锯齿形tkinter主循环帧持续时间?,python,tkinter,python-imaging-library,Python,Tkinter,Python Imaging Library,尝试使用tkinter设置PIL图像序列的动画。我的帧持续时间(ms)的图表如下所示: 有人知道是什么导致了这种锯齿状的图案吗 下面是要复制的脚本: from PIL import Image, ImageTk import Tkinter import time import sys def generate_frames(n): """ keep n under 101 * 101 """ out = [] last_pil = None

尝试使用tkinter设置PIL图像序列的动画。我的帧持续时间(ms)的图表如下所示:

有人知道是什么导致了这种锯齿状的图案吗

下面是要复制的脚本:

from PIL import Image, ImageTk
import Tkinter

import time
import sys

def generate_frames(n):
    """
    keep n under 101 * 101
    """
    out = []
    last_pil = None
    for i in range(n):
        if last_pil:
            pil_image = last_pil.copy()
        else:
            pil_image = Image.new('L', (101, 101), 255)   
        x = i / 101
        y = i % 101
        pil_image.load()[x, y] = 0
        out.append(ImageTk.PhotoImage(pil_image))
        last_pil = pil_image

    return out

def draw():
    FRAME_COUNT =5000

    master = Tkinter.Tk()

    w = Tkinter.Canvas(master, width=302, height=302)
    w.create_rectangle(49, 49, 252, 252)
    w.pack()

    frames = generate_frames(FRAME_COUNT)

    def draw_frame(f, canvas_image):
        print repr(time.time())
        frame = frames[f]
        if canvas_image is None:
            canvas_image = w.create_image((151, 151), image=frame, anchor='center')
        else:
            w.itemconfigure(canvas_image, image=frame)

        w.current_frame = frame  # save a reference
        next_frame = f + 1
        if next_frame < FRAME_COUNT:
            master.after(1, draw_frame, next_frame, canvas_image)
        else:
            sys.exit(0)

    master.after(10, draw_frame, 0, None)
    master.mainloop()


draw()
然后通过

from matplotlib import pyplot
import sys

X = []
Y = []

for index, line in enumerate(sys.stdin):
    line = line.strip()
    X.append(index)
    Y.append(float(line))

pyplot.plot(X, Y, '-')
pyplot.show()
使其多线程化无助于:

class AnimationThread(threading.Thread):

    FRAME_COUNT = 5000

    def __init__(self, canvas):
        threading.Thread.__init__(self)
        self.canvas = canvas
        self.frames = generate_frames(self.FRAME_COUNT)

    def run(self):
        w = self.canvas
        frames = self.frames
        canvas_image = None
        for i in range(self.FRAME_COUNT):
            print repr(time.time())
            frame = frames[i]
            if canvas_image is None:
                canvas_image = w.create_image((151, 151), image=frame, anchor='center')
            else:
                w.itemconfigure(canvas_image, image=frame)
            w.current_frame = frame
            time.sleep(1 * .001)

def draw_threaded():
    FRAME_COUNT = 5000
    master = Tkinter.Tk()

    w = Tkinter.Canvas(master, width=302, height=302)
    w.create_rectangle(49, 49, 252, 252)
    w.pack()

    animation_thread = AnimationThread(w)
    animation_thread.start()

    master.mainloop()

    animation_thread.join()

draw_threaded()


当60 Hz和50 Hz样本混合时,与这种干扰模式非常相似:

这可能是由于两个事物的刷新率不同(但接近)造成的。当你试着拍摄一个电视屏幕时,它看起来像一个黑条在图像中不断向下移动,或者在汽车广告中车轮似乎绕着轴向后旋转时,也会发生同样的情况。它本质上是一个扩展的


我不知道这是否是由视频驱动程序和/或硬件引起的,但几乎可以肯定是由干扰循环模式引起的。这看起来很像GC循环干扰了
for
循环(因此当内存被释放并可以分配时,锯齿波会突然下降)

我会尝试在单独的线程中运行动画,而不是在tkinter主循环中运行,看看会发生什么。好主意-谢谢。不过,这并没有什么不同(请参阅编辑后的文章),您是否尝试过使用
python-mcprofile
对其进行评测?您是否考虑过更改动画循环执行其帧的方式?与其
执行需要可变时间的任务=>等待固定时间
,不如尝试执行
执行异步任务=>如果时间正确,则继续,否则跳过
。这很可能是由于垃圾收集周期造成的-您通常会遇到这种模式。不过,我不知道你能做些什么来帮助它。
class AnimationThread(threading.Thread):

    FRAME_COUNT = 5000

    def __init__(self, canvas):
        threading.Thread.__init__(self)
        self.canvas = canvas
        self.frames = generate_frames(self.FRAME_COUNT)

    def run(self):
        w = self.canvas
        frames = self.frames
        canvas_image = None
        for i in range(self.FRAME_COUNT):
            print repr(time.time())
            frame = frames[i]
            if canvas_image is None:
                canvas_image = w.create_image((151, 151), image=frame, anchor='center')
            else:
                w.itemconfigure(canvas_image, image=frame)
            w.current_frame = frame
            time.sleep(1 * .001)

def draw_threaded():
    FRAME_COUNT = 5000
    master = Tkinter.Tk()

    w = Tkinter.Canvas(master, width=302, height=302)
    w.create_rectangle(49, 49, 252, 252)
    w.pack()

    animation_thread = AnimationThread(w)
    animation_thread.start()

    master.mainloop()

    animation_thread.join()

draw_threaded()