我有一个动态表格,行数固定(类似FIFO队列),通过tkinter的
为了使按钮的文本可编辑,我使用了BrenBarn的solution,并将循环变量引用到
当循环函数
看来我必须使用lambda表达式,否则按钮会有错误的索引,用户就会在点击正确的按钮时编辑错误的行,尽管我只使用了
有没有办法解决这个问题?用户如何单击正确的按钮并进行编辑,同时具有正确的索引并且摆脱泄漏问题?
相应的代码:
编辑:似乎确实存在更深层次的内存泄漏问题(Python本身)。这些图像不会被垃圾回收。 Python 3.x中内存缓慢泄漏,我确实使用了PIL。此外,在这里:文件名加载图像的内存泄漏没有得到适当修复 我该怎么办?因为我必须遍历一个记录列表,并使用图像更新标签。有什么解决方法吗?PhotoImage没有显式的close()函数,如果我调用del,引用将被gc'ed,无法配置标签。
after()
函数不断更新。表格内有一个可编辑文本的按钮。为了使按钮的文本可编辑,我使用了BrenBarn的solution,并将循环变量引用到
command
属性的函数调用中。当循环函数
update_content_items()
运行时,我发现内存使用量每秒都在增加MB。我可以确认,注释掉lambda表达式后,内存泄漏问题消失了。(在终端上实时运行“top”命令可见)看来我必须使用lambda表达式,否则按钮会有错误的索引,用户就会在点击正确的按钮时编辑错误的行,尽管我只使用了
self.list_items[i]
。有没有办法解决这个问题?用户如何单击正确的按钮并进行编辑,同时具有正确的索引并且摆脱泄漏问题?
相应的代码:
def update_content_items(self):
"""
Continuously fills and updates the Table with rows and content.
The size of the table rows is initially fixed by an external value at config.ini
:return: nothing
"""
if len(self.list_items) > self.queueMaxlen:
self.queueMaxlen = len(self.list_items)
self.build_table()
try:
for i in range(len(self.list_items)):
item = self.list_items[i]
self.barcodeImgList[i].image = item.plateimage
orig_image = Image.open(io.BytesIO(item.plateimage))
ein_image = ImageTk.PhotoImage(orig_image)
self.barcodeImgList[i].configure(image=ein_image)
# keeps a reference, because somehow tkinter forgets it...??? Bug of my implementation???
self.barcodeImgList[i].image = ein_image
orig_image = None
ein_image = None
#FIXME Memory LEAK?
self.numberList[i].configure(text=item.number,
command=lambda K=i: self.edit_barcode(self.list_items[K]))
self.timestampList[i].configure(text=item.timestamp)
self.search_hitlist[i].config(bg='white', cursor="xterm")
self.search_hitlist[i].unbind("<Button-1>")
if item.queryresult is not None:
if item.queryresult.gesamtstatus != 'Gruen':
self.search_hitlist[i].insert(tk.END, item.queryresult.barcode +
'\n' + item.queryresult.permitlevel)
self.search_hitlist[i].configure(bg='red', cursor="hand2")
self.search_hitlist[i].bind("<Button-1>", item.url_callback)
else:
self.search_hitlist[i].configure(bg='green', cursor="xterm")
self.search_hitlist[i].configure(state=tk.DISABLED)
self.on_frame_configure(None)
self.canvas.after(10, self.update_content_items)
except IndexError as ie:
for number, thing in enumerate(self.list_items):
print(number, thing)
raise ie
def edit_barcode(self, item=None):
"""
Opens the number plate edit dialogue and updates the corresponding list item.
:param item: as Hit DAO
:return: nothing
"""
if item is not None:
new_item_number = EditBarcodeEntry(self.master.master, item)
if new_item_number.mynumber != 0:
item.number = new_item_number.mynumber
self.list_items.request_work(item, 'update')
self.list_items.edit_hititem_by_id(item)
self.parent.master.queryQueue.put(item)
else:
print("You shouldn't get here at all. Please see edit_barcode function.")
编辑:似乎确实存在更深层次的内存泄漏问题(Python本身)。这些图像不会被垃圾回收。 Python 3.x中内存缓慢泄漏,我确实使用了PIL。此外,在这里:文件名加载图像的内存泄漏没有得到适当修复 我该怎么办?因为我必须遍历一个记录列表,并使用图像更新标签。有什么解决方法吗?PhotoImage没有显式的close()函数,如果我调用del,引用将被gc'ed,无法配置标签。
edit_barcode
中找出小部件在列表中的索引(使用event.widget),然后使用该索引获取该项。 - James Kent