python 类可以包含删除 itslef 的方法吗?

Can a python class contain a method to delete itslef?

提问人:grimad 提问时间:8/23/2023 最后编辑:D_00grimad 更新时间:8/24/2023 访问量:84

问:

我正在编写一个用于数据操作的 tkinter 类。我想找到一种方法通过单击按钮来删除对象,就像退出窗口的 X 按钮一样。
这是我的界面的样子:

tkinter interface

主窗口是一个包含 matplotlib 绘图和常规控件的类。
右边的三个“小部件”中的每一个都是一个类的对象,该类包含来自加载的 csv 文件的数据帧和一些特定的控件,例如 x 轴和 y 轴变量的选择。

我希望 X 按钮使小部件及其包含的所有内容消失,并使绘图从主对象中消失(我认为这部分必须手动完成)。
下面是 Widget 类的初始化和控件的定义:

class Data_Widget():
    """ This Class creates the main window with the curve plot and general buttons like open files, Clear all, Plot all.
    
    Arguments:
    -master: the parent window, automatically the PlotWindow class
    -data: data loaded into the widget self.data used to plot the curve
    -filepath: the filepath of the loaded data
    -color: color of the curve
    
    methods:
    -create_widget_controls : create the controls (buttons...)
    -set_widget_color : set the color of the associated curve
    -set_x_var and set_y_var : set the x and y var of the plotted curve
    -master_plot : gives the order of plotting the curve to the master class (PlotWindow) (method plot_widget)
    -master_clear_plot : gives the order of clearing the plot to the master class (PlotWindow) (method clear_widget_plots)
    -delete_widget : delete the widget
    -create_exportload_popup : export the data contained in the widget as CSV file.
                Used where widget has been created by selecting data from another widget with PlotWindow multiple selection method
    """
    def __init__(self, master, data = pd.DataFrame(), filepath='Nothing loaded', x_var=None, y_var= None, color="blue"):
        super().__init__()
        self.master = master
        # Create variables for data and plot
        self.widget_id=0                            #id of the widget   
        self.filepath=filepath                      #filepath of the loaded data
        self.data = data                            #dataframe loaded into the widget
        self.selected_data = pd.DataFrame()         #data selected by the user
        self.x_var = x_var                          #x variable of the plotted curve
        self.y_var = y_var                          #y variable of the plotted curve
        self.color = color                          #color of the plotted curve
        self.create_widget_controls()               #create the controls (buttons...)

    def __del__(self):
        print ("Object gets destroyed")

    def create_widget_controls(self):
        self.widget_frame = tk.Frame(self.master.scrollable_widgets_frame)
        self.widget_frame.pack(side=tk.TOP, fill=None, expand=False)

        empty_space = tk.Label(self.widget_frame, text="")
        empty_space.pack(side=tk.TOP, fill=tk.BOTH, expand=1)

        self.filename_label = tk.Label(self.widget_frame, text="-------------- " + os.path.basename(self.filepath) + " --------------")
        self.filename_label.pack(side=tk.TOP, fill=tk.BOTH, expand=1)

        self.x_label = tk.Label(self.widget_frame, text="X axis variable")
        self.x_label.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)
        self.x_var_dropdown_label = tk.StringVar()
        self.x_var_dropdown = tk.OptionMenu(self.widget_frame, self.x_var_dropdown_label, "")
        self.x_var_dropdown.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)

        self.y_label = tk.Label(self.widget_frame, text="Y axis variable")
        self.y_label.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)
        self.y_var_dropdown_label = tk.StringVar()
        self.y_var_dropdown = tk.OptionMenu(self.widget_frame, self.y_var_dropdown_label, "")
        self.y_var_dropdown.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)

        self.plot_button = tk.Button(self.widget_frame, text="Plot", command=self.master_plot)
        self.plot_button.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)

        self.clear_button = tk.Button(self.widget_frame, text="Clear", command=self.master_clear_plot)
        self.clear_button.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)

        self.color_button = tk.Button(self.widget_frame, text="color", bg=self.color, fg="white", command=self.set_widget_color)
        self.color_button.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)

        self.exportload_button = tk.Button(self.widget_frame, text="Export plotted\ncurve as csv", command=self.create_exportload_popup)
        self.exportload_button.pack(side=tk.BOTTOM, fill=tk.BOTH, expand=1)

        self.delete_button = tk.Button(self.widget_frame, text="X", command=self.destroy_widget)
        self.delete_button.pack(side=tk.BOTTOM, anchor=tk.NE)


        # Load the widget with the data from given by the load function of PlotWindow()
        self.x_var_dropdown['menu'].delete(0, 'end')
        self.y_var_dropdown['menu'].delete(0, 'end')
        for col in self.data.columns:
            self.x_var_dropdown['menu'].add_command(label=col, command=lambda var=col: self.set_x_var(var))
            self.y_var_dropdown['menu'].add_command(label=col, command=lambda var=col: self.set_y_var(var))

        if self.master.auto_plot.get() == 1:
            self.master_plot()
        
        # self.x_var_dropdown.bind('<<OptionMenuSelect>>', self.plot)
        # self.y_var_dropdown.bind('<<OptionMenuSelect>>', self.plot)
    
    def destroy_widget(self):
        self.widget_frame.destroy()

目前,该功能仅使帧消失,但它只是可视化的,所有数据仍然存在。
我写了一个应该用于从外部删除对象,但我无法弄清楚如何使用它,从内部删除对象。
destroy_widgetdef__del__(self)

Python matplotlib tkinter del

评论

2赞 jasonharper 8/23/2023
你完全误解了什么是为了什么。它不会(从根本上说不能)导致对象被删除,它被调用以响应实际被删除的对象(这将在您不再在任何地方引用它之后的某个时候发生)。__del__()
0赞 user2357112 8/23/2023
(严格来说,它是在 Python 检测到某个对象无法访问时调用的,而不是在实际删除对象时调用的。调用对象时尚未删除,如果 Python 不确定对象是否仍无法访问,则在调用后可能不会删除该对象。不过,关于不删除对象的要点是成立的。__del____del____del__
0赞 JonSG 8/23/2023
如果您检查了堆栈,找到传递的变量并将其从父上下文中删除,该怎么办?
0赞 grimad 8/23/2023
我想我可以从父类中删除该对象,但我认为它会很丑陋(按钮位于小部件对象中,但调用父类的方法,然后销毁子对象)感谢您对我现在完全理解的工作原理进行精确描述。__del__()

答: 暂无答案