【问题标题】:Tkinter image_create performance when inserting image into text box将图像插入文本框时的 Tkinter image_create 性能
【发布时间】:2020-03-21 21:46:33
【问题描述】:

我正在构建一个 Python (3.7.4) 应用程序来显示供应商手册文本数据库中的项目。其中一个功能是显示数据库中每个手册(也称为“产品”)的“项目名称”列表。我正在为此功能使用 Tkinter 滚动文本框小部件,并简单地使用带有选项卡的项目名称构建行来分隔它们。我想在每个项目名称前插入一个小图标(16x20 像素),并已使用下面的代码成功完成此操作。我遇到的问题是,对于数据库中的大型手册(例如,10K+ 项目名称),我从 image_create 函数中获得了显着的性能影响。在不插入图像的情况下,对于 10K 项目名称,显示项目名称列表几乎是瞬时的。插入图像可能需要 10-12 秒以上。

关于如何提高性能的任何建议?我什至研究过使用 FontForge 创建一个“图像”字体,但如果可能的话,我不想走那条路。

提前感谢您的帮助。

根据 Bryan Oakley 的要求,我在此处附上了可执行代码。如果您取消注释以下行:

tabContents_text.image_create("current", image=open_book_image)

您会看到性能上的差异。

png文件的链接是HERE


import tkinter as tk
import tkinter.scrolledtext as tkst

win = tk.Tk()
frame1 = tk.Frame(master = win)
frame1.pack(fill='both', expand='yes')
win.state('zoomed')
tabContents_text = tkst.ScrolledText(frame1, cursor="arrow", wrap="none", tabs=150, font=('helvetica', 10, 'normal'))
tabContents_text.pack(side='top')
open_book_image = tk.PhotoImage(file="C:\\Users\\rhkea\\Downloads\\document_icon.png")
product_item_list=[]
for i in range(10000):
    product_item_list.append("Item" + str(i).zfill(5))
col_count=4
row_count=2500
row_remain=0
tabContents_text.delete("1.0", "end")
row = 0
item = 0

while row < row_count:
    col = 0
    while col < col_count:
#        tabContents_text.image_create("current", image=open_book_image)
        tabContents_text.insert("end", product_item_list[item] + '\t')
        col += 1
        item += 1
    tabContents_text.insert("end", "\n")
    row += 1

col = 0
while col < row_remain:
#    tabContents_text.image_create("current", image=open_book_image)
    tabContents_text.insert("end", product_item_list[item] + '\t')
    col += 1
    item += 1
tabContents_text.insert("end", "\n")

win.mainloop()

【问题讨论】:

  • 如果您可以创建我们可以运行的代码,这将有所帮助。例如,您可以创建一个循环来创建 10,000 个项目,而不是从数据库中读取。
  • 你可以使用page的概念来展示item,即将item分成组,每组包含一定数量的item。每次加载一组项目。
  • Bryan - 我在帖子中添加了简单的可执行代码以及指向 .png 图像的链接。如果您取消注释 image_create 语句,您将希望看到我正在谈论的性能差异。谢谢!
  • 同样的代码没必要发两次,只会让问题更混乱。
  • 知道了 - 删除了原始代码 sn-p。谢谢。

标签: python-3.x tkinter


【解决方案1】:

不幸的是,我认为没有更好的表现。但是你可以使用.update() 立即显示图像,而不是在代码中阻止它。

我不知道第二个while循环的目的是什么

你可以试试这段代码,运行后会继续加载图片:

import tkinter as tk
import tkinter.scrolledtext as tkst

win = tk.Tk()
frame1 = tk.Frame(master = win)
frame1.pack(fill='both', expand='yes')
win.state('zoomed')
tabContents_text = tkst.ScrolledText(frame1, cursor="arrow", wrap="none", tabs=150, font=('helvetica', 10, 'normal'))
tabContents_text.pack(side='top')
open_book_image = tk.PhotoImage(file="document_icon.png")
product_item_list=[]
for i in range(10000):
    product_item_list.append("Item" + str(i).zfill(5))
col_count=4
row_count=2500
row_remain=0
tabContents_text.delete("1.0", "end")
row = 0
item = 0

try:
    while row < row_count:
        col = 0
        while col < col_count:
            tabContents_text.image_create("end", image=open_book_image) # It's "end" instead of current.
            tabContents_text.insert("end", product_item_list[item] + '\t')
            win.update() # update right away.
            col += 1
            item += 1
        tabContents_text.insert("end", "\n")
        win.update()
        row += 1

    col = 0
    # This while loop seems that it will create two empty lines
    while col < row_remain:
        tabContents_text.image_create("current", image=open_book_image)
        tabContents_text.insert("end", product_item_list[item] + '\t')
        win.update()
        col += 1
        item += 1
    tabContents_text.insert("end", "\n")

except BaseException: # Catch the raised exception when you close the window if it doesn't load image completely.
    pass

except Exception as e:
    print(e.args)


win.mainloop()

或许使用.after()也可以。

【讨论】:

    【解决方案2】:

    您可以将图像和文本组合成一个Label,然后使用.window_create(...) 插入Text 框中:

    font = tabContents_text.cget('font') # get the Text font
    for i in range(len(product_item_list)):
        # create label with both image and text
        lbl = tk.Label(tabContents_text, text=product_item_list[i]+'\t',
                       image=open_book_image, compound='left',
                       bg='white', font=font)
        # insert the label into text box
        tabContents_text.window_create('end', window=lbl)
        # insert line break after showing 'col_count' items
        if i%col_count == col_count-1:
            tabContents_text.insert('end', '\n')
    

    它可以将插入文本框中的项目总数减少一半。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-06
      • 2017-01-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多