考虑以下小型Python GUI程序,用户可以反复单击按钮在窗口1和窗口2之间循环:
import tkinter
class Window1:
def __init__(self, parent):
# Initialize a new GUI window
self.parent = parent
self.window = tkinter.Toplevel(self.parent)
self.window.title('Window 1')
# Make a button to launch Window 2
launch_window_2_button = tkinter.Button(self.window, text='Launch Window 2')
launch_window_2_button.config(command=self.launch_window_2)
launch_window_2_button.pack()
def launch_window_2(self):
self.window.destroy()
Window2(self.parent)
class Window2:
def __init__(self, parent):
# Initialize a new GUI window
self.parent = parent
self.window = tkinter.Toplevel(self.parent)
self.window.title('Window 2')
# Make a button to launch Window 1
launch_window_1_button = tkinter.Button(self.window, text='Launch Window 1')
launch_window_1_button.config(command=self.launch_window_1)
launch_window_1_button.pack()
def launch_window_1(self):
self.window.destroy()
Window1(self.parent)
if __name__ == "__main__":
# Initialize and hide the root GUI
# (each class will spawn a new window that is a child of the root GUI)
root = tkinter.Tk()
root.withdraw()
Window1(root) # Start by spawning Window 1
root.mainloop()
问题1:由于每个新类都是从另一个类中实例化的,这是内存泄漏吗?
问题2:这是编写此应用程序的最正确和Pythonic方式吗?
问题3:假设问题1的答案为否,如果我将Window1(self.parent)
更改为self.something = Window1(self.parent)
该怎么办?现在有一个参考,现在是内存泄漏吗?
答案 0 :(得分:3)
问题1:由于每个新类都是从另一个类中实例化的,这是内存泄漏吗?
没有。而且我认为你在内存泄漏和未使用的对象引用之间存在一些混淆。 @kindall在你的问题评论中很好地解释了它。
了解情况的最佳方法是知道tkinter.TopLevel(..)
构造函数是side-effects based.它将在根对象中保存对窗口的引用,以便它知道如何处理各种视窗。 您的类的构造函数也是如此。一旦创建了self.window
并且某种程度上root
引用了它,它的工作就完成了。此对象的引用也是如此,尽管没有明确说明(请参阅下面的问题3的回答)。
问题2:这是编写此应用程序的最正确和Pythonic方式吗?
对象Window1
和Window2
对象的引用未被使用的事实也让我感到困惑。除此之外,我可能还会在对象中存储窗口元素(按钮等)的引用 - 它们可能没有立即使用,但它们可能会在以后使用。
问题3:假设对问题1的回答是否定的,如果我做了什么 改变了以下几行:
窗口1(self.parent)
为:
self.something = Window1(self.parent)
现在有一个参考,现在是内存泄漏吗?
想想以下几行:
launch_window_2_button.config(command=self.launch_window_2)
为了使该行有效,tkinter必须在某处存储self.launch_window2
(以及self
)的引用,因此您的self.something
根本没有做任何重要的事情。 :)