【问题标题】:Tkinter performance when packing many widgets打包许多小部件时的 Tkinter 性能
【发布时间】:2016-11-13 17:37:07
【问题描述】:

我正在使用 Tkinter 在 python 中制作一个 GUI,并且在将许多小部件打包到屏幕上时遇到了一些性能问题,例如打包一个 50x50 的按钮网格需要几秒钟。

似乎是在屏幕上绘制(或排列?)小部件的过程需要时间。我尝试过同时使用网格和位置几何管理器。

我想知道使用多处理是否可以加快速度?我欢迎任何其他可以显着加快速度的建议。

import Tkinter as tk

root = tk.Tk()
frame = tk.Frame(root)
for i in range(50):
    for j in range(50):
        widget = tk.Frame(frame, bd=2, relief='raised', height=10, width=10)
        widget.grid(row=i, column=j) # using place is barely quicker
tk.Button(root, text='pack', command=frame.pack).pack()
root.mainloop()

【问题讨论】:

  • Tkinter 不是线程安全的,因此多处理几乎肯定无济于事,我个人发现,在某些情况下,将小部件放在画布上 canvas.create_window 重绘更快,但更难调整大小/操作。
  • @TadhgMcDonald-Jensen 我刚刚用上面的例子试过了,如果有的话差别很小。
  • 我的意思是...您正在实例化 2500 个对象,这些对象都需要实例化、生成唯一键、传送到 Tcl 解释器并在那里实例化、来回绑定,然后排列。就 GUI 而言,从一种解释语言到另一种解释语言的包装器通常需要 2500 个对象。你的目标是什么?如果你只是想要一个类似网格的构造,不要使用 2500 帧,使用画布和draw 一些正方形(更少/更简单的对象)
  • 给定一个单元格的点击,游戏逻辑需要单元格坐标,而不是单元格字符串 id。给定 k 像素 x k 像素单元,在 x, y 处单击的单元坐标将为 x//k, y//k。我只会在绑定到画布上的“”的单击事件处理程序中使用它。
  • @R4PH43L 在引用其他网站时,指出cross-posting is frowned upon 通常会有所帮助

标签: python python-2.7 user-interface tkinter


【解决方案1】:

正如 cmets 中所建议的,最好的解决方案最终是使用画布并在其上绘制,而不是打包这么多小部件,这似乎对其速度有绝对的限制。

我通过有效地截取屏幕截图来使用内置按钮来创建未点击和点击状态的图像。假设图像文件存储为im_up.pngim_down.png,那么下面的代码说明了画布解决方案。

import Tkinter as tk
# Uses Python Imaging Library.
from PIL import Image as ImagePIL, ImageTk

root = tk.Tk()
canvas = tk.Canvas(root, height=500, width=500, highlightthickness=0)
canvas.pack()
images = dict()
for name in ['up', 'down']:
    im = ImagePIL.open('im_{}.png'.format(name))
    # Resize the image to 10 pixels square.
    im = im.resize((10, 10), ImagePIL.ANTIALIAS)
    images[name] = ImageTk.PhotoImage(im, name=name)
def set_cell_image(coord, image):
    # Get position of centre of cell.
    x, y = ((p + 0.5) * 10 for p in coord)
    canvas.create_image(x, y, image=image)
for i in range(50):
    for j in range(50):
        set_cell_image((i, j), images['up'])
def click(event):
    coord = tuple(getattr(event, p)/10 for p in ['x', 'y'])
    set_cell_image(coord, images['down'])
canvas.bind('<Button-1>', click)
root.mainloop()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多