遍历数组停止增加索引(原图:消息小部件文本随机不刷新)
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
将为您提供 SkItems
中 sSkItem
的 首次出现 的索引,而不是循环中当前项目的索引,因为您毫无疑问 expect/want。如果有任何重复的项目(正如您观察到的那样),这将会中断。
要解决这个问题,您可以使用自己的计数器来跟踪索引,例如:
currentIndex = 0
for sSkItem in SkItems:
iSkCol = currentIndex
currentIndex += 1
或者使用循环的正常范围遍历 indexes 而不是 items.
我在 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
将为您提供 SkItems
中 sSkItem
的 首次出现 的索引,而不是循环中当前项目的索引,因为您毫无疑问 expect/want。如果有任何重复的项目(正如您观察到的那样),这将会中断。
要解决这个问题,您可以使用自己的计数器来跟踪索引,例如:
currentIndex = 0
for sSkItem in SkItems:
iSkCol = currentIndex
currentIndex += 1
或者使用循环的正常范围遍历 indexes 而不是 items.