在多个标签中多次更改图像的最佳方法是什么?

时间:2019-04-10 16:06:17

标签: python tkinter

我需要一些有关如何进行此项目的建议。我有多年的编程经验,但在过去的几周才开始接触Python。

此Python 3程序的tkinter屏幕上有150个图标。图标是标签窗口小部件,根据从文本文件读入程序的设备状态,显示三个20x20 png图形之一。每个图标每天都需要更改几次。

在这种情况下,任何建议使用哪种方法来显示这些图标,我们将不胜感激。

我做了几次尝试。理想情况下,StringVar()/ textvariable类型方法会很好(这对于更改标签中的文本非常有用),但是我找不到用于图像的类似方法。一遍又一遍地简单地将同一标签推到屏幕上是行不通的,因为该程序最终会崩溃,导致“内存不足”。

编辑: 我已经使用键/值对解决了这个问题,因此每个循环都不会创建一个新标签。该方法仅在单个实例上起作用,但是一旦将其放入此循环结构中,它就会崩溃并显示“ TypeError:'str'对象不支持项目分配”。我创建了这个简单的例程,该例程反映了我在较大项目中遇到的问题。我该如何使用它?

import tkinter as tk
import time

window = tk.Tk()
window.title("PiStatus")
window.geometry("500x500+0+0")

ct = 0
# You can use any small images for this, mine are 20x20 pixels.
pc_on_icon = tk.PhotoImage(file="1.png")
pc_active_icon = tk.PhotoImage(file="2.png")
pc_off_icon = tk.PhotoImage(file="0.png")

# This loop creates the base 15x10 grid of labels, each with a unique name.
for ypos in range(10):
    for xpos in range(15):
        label_name = "icon" + str(xpos) + "-" + str(ypos)
        label_name = tk.Label(window, image=pc_on_icon)
        label_name.grid(row=ypos, column=xpos)

while True:

# These statements cycle through the 3 images
    if ct == 0:
        turn = pc_off_icon
    elif ct == 1:
        turn = pc_on_icon
    else:
        turn = pc_active_icon

# This loop references each label giving it a different image each time around.
    for ypos in range(10):
        for xpos in range(15):
            label_name = "icon" + str(xpos) + "-" + str(ypos)
            label_name['image'] = turn  # This is where the error occurs.

    ct += 1

    if ct == 3:
        ct = 0

    window.update()

window.mainloop()

1 个答案:

答案 0 :(得分:0)

我们可以创建一个自定义小部件来封装为一个特定设备显示多个状态图标的功能。让我们将其称为MultiStateIcon并从tk.Frame派生出来。

此小部件将包含子tk.Label小部件的集合,每个状态/图像一个。所有标签都将填充重叠,但是只有一个标签(与当前状态相对应)可见(其他标签可以使用pack_forget()隐藏)。

然后,您只需要创建一个MultiStateIcon的网格(或所需的任何布局),并按照文本文件的指示更改它们的状态即可。


为演示起见,我使应用程序定期(每10ms)将一个随机选择的设备的状态设置为随机选择的状态。

示例脚本:

import Tkinter as tk
import PIL.Image, PIL.ImageTk
from random import randrange


class MultiStateIcon(tk.Frame):
    def __init__(self, parent, images, *args, **kwargs):
        tk.Frame.__init__(self, parent, *args, **kwargs)

        self.images = images
        self.labels = []

        for image in images:
            l = tk.Label(self, image = image)
            l.pack()
            self.labels.append(l)

        self.set_state(0)

    def set_state(self, n):
        for i in range(len(self.labels)):
            if i == n:
                self.labels[i].pack()
            else:
                self.labels[i].pack_forget()

class TestApp(tk.Tk):
    def __init__(self, image_paths, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        self.title("Test")
        self.frame = tk.Frame(self)
        self.frame.pack()

        self.images = []
        for image_path in image_paths:
            img = PIL.ImageTk.PhotoImage(PIL.Image.open(image_path))
            self.images.append(img)

        self.icons = []
        for r in range(10):
            for c in range(15):
                icon_lbl = MultiStateIcon(self.frame, self.images)
                icon_lbl.grid(row=r, column=c)
                self.icons.append(icon_lbl)

        self.after(1000, self.change_random_icon)

    def change_random_icon(self):
        n = randrange(0, len(self.icons))
        state = randrange(0, len(self.images))
        self.icons[n].set_state(state)
        self.after(10, self.change_random_icon)

def run():
    app = TestApp(["multiicon_0.png", "multiicon_1.png", "multiicon_2.png"])    
    app.mainloop()

run()

我使用的图像:

该应用的屏幕截图(一个开始,另一个过一会儿-内存使用情况似乎稳定):

相关问题