遍历数组停止增加索引(原图:消息小部件文本随机不刷新)

Loop through array stops increasing index (Orig: Message widget text randomly not refreshing)

我在 txt 文件中有一个自动生成的报告,每 5 秒左右更新一次,如下所示:

Report Data Start Time:;00:00 25/08/2016Report;Va1;Val2;Val3;Val4;Val5;Val6;Val7
X;6;4;0;0;32;3;0.8125
Y;2;1;0;0;0;0;0
Z;5;1;0;0;0;0;0
[empty last line]

在 tkinter 中,我创建了一个 GUI,它可以读取数据并以一种 table 的方式实时显示它。这些小部件是按程序生成的,并以预定义的名称存储在集合中,稍后将根据此名称调用它们并修改它们的内容。 但是,当读取数据并将其放入小部件时,一些看似随机的单元格是空的。当我说随机时,它实际上非常一致(col2、row2 和 col5 到 7,row2 到 3)但是当我以某种方式更改报告文件时,新值可能会出现也可能不会出现(这真的很随机​​)。

(显着)具有相同问题的代码的缩短版本:

import tkinter as tk

class MainApplication(tk.Frame):

    global SkillWidgets
    SkillWidgets = {}


    def __init__(self, parent, *args, **kwargs):
        tk.Frame.__init__(self, parent, *args, **kwargs)       
        self.parent = parent
        self.create_stuff()
        self.refresh()


    def create_stuff(self):        
        screen_width = tkGUI.winfo_screenwidth()
        screen_height = tkGUI.winfo_screenheight()
        iSW = screen_width/1000
        iSH = screen_height/1000

        tkFrSkills = tk.Frame(tkGUI)
        tkFrSkills.place(x=(100*iSW)+20, y=20+(50*iSH), bordermode=tk.INSIDE, height=screen_height/2-(100+50*iSH), width=screen_width)

        for iRow in range(1,4):
            for iCol in range(1,8):
                tkMsg = tk.Message(tkFrSkills, text="", font=("Arial", 36), relief = tk.GROOVE, bd = 2, width = 100)
                tkMsg.place (x=((iCol-1)*100*iSW), y=(75*iRow*iSH)-(75*iSH), bordermode=tk.INSIDE, width = 100*iSW, height = 75*iSH)
                SkillWidgets[(iRow,iCol)] = tkMsg



    def refresh(self):
        fSkills = open("report.txt")
        sSkContents = fSkills.read()
        fSkills.close()

        SkLines = sSkContents.split("\n")
        del(SkLines[len(SkLines)-1])

        iSkRow = 0
        for sSkLine in SkLines:  
            if "X" in sSkLine:
                iSkRow = 1
            if "Y" in sSkLine:
                iSkRow = 2
            if "Z" in sSkLine:
                iSkRow = 3       

            if iSkRow > 0:
                SkItems = sSkLine.split(";")
                SkItems[1], SkItems[2], SkItems[3], SkItems[4] = SkItems[2], SkItems[4], SkItems[1], SkItems[3]
                SkItems[2] = str(int(SkItems[3])-int(SkItems[1]))              
                del(SkItems[0])                                      
             ***print(SkLines[iSkRow])

                for sSkItem in SkItems:

                    iSkCol = SkItems.index(sSkItem)+1
                ****print("Row=",iSkRow,"Col=",iSkCol,"sSkItem=",sSkItem)
               *****print("Row=",iSkRow,"Col=",iSkCol,"widget text =", SkillWidgets[(iSkRow,iSkCol)].cget("text"))
                    SkillWidgets[(iSkRow,iSkCol)].config(text = sSkItem)
                ****print("Row=",iSkRow,"Col=",iSkCol,"sSkItem=",sSkItem)
               *****print("Row=",iSkRow,"Col=",iSkCol,"widget text =", SkillWidgets[(iSkRow,iSkCol)].cget("text"))
                    print("----------")


        self.after(1000,self.refresh)

if __name__ == "__main__":
    tkGUI = tk.Tk()
    tkGUI.attributes("-fullscreen", True)
    MainApplication(tkGUI).pack(side="top", fill="both", expand=True)
    tkGUI.mainloop()

编辑: 我忘了提到我试图打印我输入的值(代码调整 - 我突出显示了一些星号的地方

*** 此打印正确给出了相关行,但是由于某种原因它运行了两次循环,给出了

X;6;4;0;0;32;3;0.8125
Y;2;1;0;0;0;0;0
Z;5;1;0;0;0;0;0

**** 此打印正确给出了我要输入到小部件的值

***** 这篇文章触及了问题的根源: a) 如果输入的值为“1”,则循环根本不经过 2:2,而是只给出 2:1 两次,第一次打印显示小部件的值为“1”(因为我猜它刚刚通过 2:1) b) 如果输入的值是“2”或更多,它按预期工作 - 循环按预期 2:1、2:2、2:3

(如果要输入的值 = 1)

Row= 2 Col= 1 sSkItem= 1
Row= 2 Col= 1 widget text = 
Row= 2 Col= 1 sSkItem= 1
Row= 2 Col= 1 widget text = 1
----------
Row= 2 Col= 1 sSkItem= 1
Row= 2 Col= 1 widget text = 1
Row= 2 Col= 1 sSkItem= 1
Row= 2 Col= 1 widget text = 1
----------

如果要输入的值 > 1

Row= 2 Col= 1 sSkItem= 1
Row= 2 Col= 1 widget text = 
Row= 2 Col= 1 sSkItem= 1
Row= 2 Col= 1 widget text = 1
----------
Row= 2 Col= 2 sSkItem= 3
Row= 2 Col= 2 widget text = 
Row= 2 Col= 2 sSkItem= 3
Row= 2 Col= 2 widget text = 3
----------

c) 在这两种情况下,循环都不会通过 cols 5to7

遍历第 2 行和第 3 行

编辑2: 有趣的......现在我添加了更多的印刷品(虽然没有别的)并且输入 2:2 的值是“1”现在似乎不是问题(2:3 到 3:7 是虽然仍然不在循环中)。

编辑 3: 我似乎找到了原因...此时,对于第 2 行和第 3 行,它只是在第 5 次迭代时停止增加索引(未加载索引为 4 的项目,而是再次加载索引为 3 的项目)

            for sSkItem in SkItems:
                print(SkItems)
                print("item3: ", SkItems[3])
                print("item4: ", SkItems[4])
                print("item5: ", SkItems[5])
                print("item6: ", SkItems[6])
                iSkCol = SkItems.index(sSkItem)
                print("index", iSkCol)
                print("Row=",iSkRow,"Col=",iSkCol,"sSkItem=",sSkItem)
                print("Row=",iSkRow,"Col=",iSkCol,"widget text =", SkillWidgets[(iSkRow,iSkCol)].cget("text"))
                SkillWidgets[(iSkRow,(iSkCol))].config(text = sSkItem)
                print("Row=",iSkRow,"Col=",iSkCol,"sSkItem=",sSkItem)
                print("Row=",iSkRow,"Col=",iSkCol,"widget text =", SkillWidgets[(iSkRow,iSkCol)].cget("text"))

打印结果如下:

['1', 1, '2', '0', '0', '0', '0']
item3:  0
item4:  0
item5:  0
item6:  0
index 1
Row= 1 Col= 1 sSkItem= 1
Row= 1 Col= 1 widget text = 
Row= 1 Col= 1 sSkItem= 1
Row= 1 Col= 1 widget text = 1
---
['1', 1, '2', '0', '0', '0', '0']
item3:  0
item4:  0
item5:  0
item6:  0
index 2
Row= 1 Col= 2 sSkItem= 2
Row= 1 Col= 2 widget text = 
Row= 1 Col= 2 sSkItem= 2
Row= 1 Col= 2 widget text = 2
---
['1', 1, '2', '0', '0', '0', '0']
item3:  0
item4:  0
item5:  0
item6:  0
index 3
Row= 1 Col= 3 sSkItem= 0
Row= 1 Col= 3 widget text = 
Row= 1 Col= 3 sSkItem= 0
Row= 1 Col= 3 widget text = 0
---
['1', 1, '2', '0', '0', '0', '0']
item3:  0
item4:  0
item5:  0
item6:  0
index 3
Row= 1 Col= 3 sSkItem= 0
Row= 1 Col= 3 widget text = 0
Row= 1 Col= 3 sSkItem= 0
Row= 1 Col= 3 widget text = 0
---

我认为您的问题在于 for 循环的不正确使用,特别是

for sSkItem in SkItems:
    iSkCol = SkItems.index(sSkItem)+1

将为您提供 SkItemssSkItem 首次出现 的索引,而不是循环中当前项目的索引,因为您毫无疑问 expect/want。如果有任何重复的项目(正如您观察到的那样),这将会中断。

要解决这个问题,您可以使用自己的计数器来跟踪索引,例如:

currentIndex = 0

for sSkItem in SkItems:
    iSkCol = currentIndex
    currentIndex += 1

或者使用循环的正常范围遍历 indexes 而不是 items.