有什么方法可以加快Tkinter中可滚动画布的绘制速度?

时间:2019-11-27 18:08:55

标签: python canvas tkinter tcl tk

因此,在发布有关此问题的另一个问题之后,我意识到该问题仅发生在我的自定义调整大小绑定中。当我按窗口的默认边缘调整窗口大小时,不会发生问题,并且画布的内容会准确绘制-但是,当使用我的自定义调整大小绑定时,画布的内容会滞后并且滞后于窗口的真实位置。

import tkinter as tk


def resize(self, event=None):
    y=root.winfo_height()

    x1 = root.winfo_pointerx()
    x0 = root.winfo_rootx()

    root.geometry("%sx%s" % (x1-x0,y))

root=tk.Tk()

canvas = tk.Canvas(root,bg='red')

canvas.pack(padx=20,pady=20)

inside=tk.Frame(root)
inside.pack(fill='both')

for i in range(10):
    x=tk.Label(inside,text='Lsdkfjhaskfjhskljdfhaskjfhksfhkjasdhf')
    x.pack()

g=tk.Button(root,text='Drag to resize')

g.bind('<B1-Motion>',resize)
g.pack()

canvas.create_window(5,5,window=inside,anchor='nw')

原始内容: enter image description here

使用按钮通过手动绑定调整窗口大小时的屏幕截图-您可以看到在调整窗口大小时内容不可见,并落后于画布所在的位置。

enter image description here

如果我在调整大小函数开始时调用root.update(),则此问题已解决,但是这会导致递归深度错误,使成千上万的调用在如此短的时间内进行更新。

最后重复一遍。当使用默认窗口调整大小时,在窗口的边缘会微调画布,以完美的绘制速度完美调整画布的大小,并且内容始终保持可见。为什么我的绑定行为不同?

2 个答案:

答案 0 :(得分:2)

通常,几何计算非常复杂(并且Tk在后台有一些相当复杂的求解器来处理它们),因此它们仅在GUI被视为“空闲”时才运行。当事件队列原本会阻塞,等待来自外部世界的下一条消息时(即,没有其他人排队等待立即)时,就会发生空闲。 Tk还以相同的方式推迟重绘(另一种实际上非常昂贵的操作);它使UI看起来比实际速度快得多。这在20年前甚至更重要的时候都是至关重要的,但现在仍然非常有用。

但是如果总有大量事件发生,它就会中断,并且拖动可以做到这一点,尤其是在涉及调整大小时。这就是为什么您可以执行update idletasks(以Tcl / Tk表示法)和update_idletasks()(以Tkinter表示法)的原因。这样做是立即处理所有挂起的空闲事件回调,而不会接收其他真实事件,运行挂起的调整大小计算并重新绘制。与完整的update()相比,触发重入事件处理的可能性要小得多(这是您遇到的问题(以及在正常情况下为何update is considered harmful的原因)。

请注意,重要的是让事件循环本身有一些时间要处理,因为处理小部件调整大小的部分不可避免地是通过真实事件来完成的(因为它们会影响OS / GUI)。到目前为止,最好的方法就是确保尽快从事件处理程序中正常返回。

答案 1 :(得分:-1)

您是否使用了正确的绑定事件?尝试''

g.bind('<ButtonRelease-1>',resize)