【发布时间】:2016-06-11 19:25:45
【问题描述】:
我有一个使用 tkinter 的 Python 3.5 应用程序,并在画布中动态创建/删除小部件。我注意到在窗口调整大小回调期间使用 w.destroy() 销毁小部件时,回调正确完成,但窗口正在重置为其原始大小。
我尝试使用 self.after(1000, self.resize) 延迟 w.destroy() 并且这种方法有效,但是在触发回调时向下拖动/按住光标时,调整大小会跳回无论如何。
有人建议即时删除小部件并释放内存吗?
更新: 作为一种解决方法,我使用 w.delete=True 标记要删除的小部件,并在“后”回调中删除标记为删除的小部件。
这是一个简化的示例来说明问题:
更新:将代码简化为重现问题的最低限度。
from tkinter import ALL, N, E, W, S, Canvas, Tk, ttk
class Resize(Tk):
def __init__(self):
super().__init__()
self.init = True
self.canvas = None
self.position_window()
self.create_canvas()
def resize(self):
if self.init:
self.init = False
return
# delete(ALL) will remove the widget from the display, but widget
# remains in memory as child of canvas. Resizing works ok.
self.canvas.delete(ALL)
# widget.destroy() will release memory of widget, but blocks/resets resizing.
# Window gets resized by 1-2 pixels and jumps back to its original size.
[child.destroy() for child in self.canvas.winfo_children()]
def create_canvas(self):
self.columnconfigure(0, weight=1)
self.rowconfigure(0, weight=1)
self.canvas = Canvas(self)
self.canvas.grid(row=0, column=0, sticky=(N, S, W, E))
self.canvas.bind('<Configure>', lambda *args: self.resize())
entry = ttk.Label(self.canvas, text='Some dummy text')
self.canvas.create_window(20, 20, window=entry, anchor='w')
def position_window(self):
self.resizable(1, 1)
sceenwidth = self.winfo_screenwidth()
screenheight = self.winfo_screenheight()
self.update_idletasks()
width = 600
height = 300
left = sceenwidth / 2 - width / 2
top = (screenheight / 2 - height / 2) / 3
self.geometry("%dx%d%+d%+d" % (width, height, left, top))
if __name__ == '__main__':
Resize().mainloop()
【问题讨论】:
-
你为什么要删除它们,然后它们会立即重新创建它们?您要解决的真正问题是什么?
-
@BryanOakley 上面的代码只是一个示例,用于重现在回调期间销毁小部件时滚动中止的问题。我同意代码可能不是很合乎逻辑...基于您在其他地方的一些指责,我正在创建一个 Table 小部件,该小部件仅通过在画布中显示少数行来处理数千行。调整画布大小时,我删除了多余的行及其小部件。那时,调整大小正在重置,没有任何错误。顺便提一句。我已经简化了代码。
-
您找到解决方案了吗?我的项目也有类似的问题
-
@DV,错过了您的评论...不,没有找到解决方案。除非您将使用 Electron/Angular 称为解决方案 :-)
标签: python-3.x tkinter window-resize tkinter-canvas