1分钟后标签图像和串行超时的Tkinter刷新问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1分钟后标签图像和串行超时的Tkinter刷新问题相关的知识,希望对你有一定的参考价值。

我试图从arduino获取串行数据数组,并在我的Raspberry Pi 3中使用它们作为Python3标签的坐标。我可以使用串行获取数组并按我想要的方式放置标签。程序有效。但第一个问题是我可以看到闪烁和延迟时间随着时间的推移而变得越来越糟糕。第二个问题是程序在几分钟后停止工作。

我尝试了ser.flushInput(),我在每个地方清除了我的数组,结果是一样的。

from tkinter import *
import serial
root = Tk()
root.geometry("1024x600")
ser = serial.Serial('/dev/ttyAMA0',115200)
ser.timeout=None

data=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
data1=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
image=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
label=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
x1=[210,210,210,370,370,370,530,530,530,690,690,690,850,850,850,850]
y1=[440,325,75,440,325,75,440,325,75,440,325,75,440,325,200,75]

image_gri=PhotoImage(file="/home/pi/python/gri.gif")
image_kirmizi = PhotoImage(file="/home/pi/python/kirmizi.gif")
image_yesil = PhotoImage(file="/home/pi/python/yesil.gif")

def kontrol():
 data=[]
 ser.flush()
 ser.flushInput()
 data = ser.read(32)
 #print(data)

 for i in range(0,16):
      if data[i]==49 and data[i+16]==49:

            image[i]=image_yesil
            label[i] = Label(root, image=image[i])
            label[i].place(x=x1[i],y=y1[i])


      elif data[i]==49 and data[i+16]==48:
            image[i]=image_kirmizi
            label[i] = Label(root, image=image[i])
            label[i].place(x=x1[i],y=y1[i])

      else :
            image[i]=image_gri
            label[i] = Label(root, image=image[i])
            label[i].place(x=x1[i],y=y1[i])


 ser.flush()
 ser.flushInput()               
 root.after(50,kontrol)
 root.update()
kontrol()
#root.after(50,kontrol)
mainloop()

我希望该程序可以工作长达12小时,并且在工作时看不到闪烁。

答案

问题是您在每次运行中添加了16个Label小部件,这些小部件保存在内存中并且每次都会处理。旧标签永远不会被删除。

要解决此问题,您可以在使用label[i].destroy()创建新标签时删除以前的标签。更好的方法是使用label[i].config(image=...)更新现有标签,而不是创建新标签。

下面是一个完整的示例(一些代码被注释掉,并使用随机数据和虚拟图像,所以使用Python 3的任何人都可以在没有外部依赖的情况下运行它):

import random
from tkinter import *
# import serial

root = Tk()
root.geometry("1024x600")
# ser = serial.Serial('/dev/ttyAMA0', 115200)
# ser.timeout = None

# If you have the images, use this:
#IMAGE_GRI = PhotoImage(file="/home/pi/python/gri.gif")
#IMAGE_KIRMIZI = PhotoImage(file="/home/pi/python/kirmizi.gif")
#IMAGE_YESIL = PhotoImage(file="/home/pi/python/yesil.gif")

# Otherwise, create some dummy images for demonstration purposes:
WIDTH = 64
HEIGHT = 64
DATA = ','.join(['0x00' for i in range(WIDTH * HEIGHT // 8)])
BITMAP = '#define im_width %d
#define im_height %d
static char im_bits[] = {
%s
};' % (WIDTH, HEIGHT, DATA)
IMAGE_GRI = BitmapImage(data=BITMAP, background="grey")
IMAGE_KIRMIZI = BitmapImage(data=BITMAP, background="red")
IMAGE_YESIL = BitmapImage(data=BITMAP, background="green")

# Initialize with grey images (you may choose a different image, of course)
label = [Label(root, image=IMAGE_GRI) for i in range(16)]

x1 = [210, 210, 210, 370, 370, 370, 530, 530, 530, 690, 690, 690, 850, 850, 850, 850]
y1 = [440, 325, 75, 440, 325, 75, 440, 325, 75, 440, 325, 75, 440, 325, 200, 75]

# Place the images only once:
for i in range(16):
    label[i].place(x=x1[i], y=y1[i])

def kontrol():
    data = []
    # ser.flush()
    # ser.flushInput()
    # data = ser.read(32)
    # Create random data for demonstration purposes:
    data = [random.choice((48, 49)) for i in range(32)]
    #print(data)

    for i in range(16):
        if data[i] == 49 and data[i+16] == 49:
            label[i].config(image=IMAGE_YESIL)  # update image!
        elif data[i] == 49 and data[i+16] == 48:
            label[i].config(image=IMAGE_KIRMIZI)  # update image!
        else:
            label[i].config(image=IMAGE_GRI)  # update image!

    # ser.flush()
    # ser.flushInput()
    root.after(50, kontrol)
    # root.update()  # Not necessary! Use root.update_idletasks() if necessary.

kontrol()
mainloop()

以上是关于1分钟后标签图像和串行超时的Tkinter刷新问题的主要内容,如果未能解决你的问题,请参考以下文章

多线程 Python Tkinter 串行监视器中的按钮问题

如何更新 Tkinter 标签小部件的图像?

Python,在标签中的 Tkinter 中显示 openCv 图像

登录页面刷新时会话超时

Tkinter未在标签中显示图像[重复]

Python Tkinter 从标签中删除/删除图像