让一个类删除自己

时间:2015-05-30 20:44:13

标签: python class tkinter

我正在使用Tkinter创建一个程序,它将创建一个事件列表。我用了一堂课来制作一个活动。如果单击添加事件按钮(显示第二个脚本),它将创建该类的新实例,从而延长列表。但是,我还希望能够从列表中删除事件。我正在尝试将删除按钮附加到每个类,当单击时,将删除该类。这是我的类脚本(classes.py)中的代码:

from Tkinter import *

class agendaEvent:

    def __init__(self, master):
        self.frame = Frame(master, padx=10, pady=10)
        self.frame.pack(side=TOP)
        self.name = Entry(self.frame)
        self.name.grid(row=1, column=0)
        self.time = Entry(self.frame, width=10)
        self.time.grid(row=1, column=1, padx=5)
        self.label1 = Label(self.frame, text="Event Name")
        self.label1.grid(row=0, column=0)
        self.label2 = Label(self.frame, text="Minutes")
        self.label2.grid(row=0, column=1)
        self.remove = Button(self.frame, text="Remove", command=agendaEvent.remove)
        self.remove.grid(row=1, column=3)

    def remove(agendaEvent):
        del agendaEvent

当我按下删除按钮时,我收到错误

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python27\lib\lib-tk\Tkinter.py", line 1532, in __call__
    return self.func(*args)
TypeError: unbound method remove() must be called with agendaEvent instance as first argument (got nothing instead)

如何调用agendaEvent的实例?或者有更好的方法来解决这个问题吗?这是主脚本(main.py)的代码:

from Tkinter import *
import classes


def addEvent():
    classes.agendaEvent(root)

root = Tk()

addEventButton = Button(root, text="Add Event", command=addEvent)
addEventButton.pack(side=BOTTOM)

root.mainloop()

3 个答案:

答案 0 :(得分:0)

您可以使用.destroy()删除标签和其他小部件(不确定全部)。如果以某种方式存储类的实例,您可以忘记或销毁它们,但如果实例只是一个实例,那么我就不会看到您的问题(阅读,我无法帮助您)。如果您想学习如何使用Tkinter构建GUI,您应该在youtube上查看有关该主题的sentdex视频。

这就是我使用按钮的方式制作tkinter小部件,就像我想你要做的那样:

  1. 我创建了一个计数器变量,用于计算列表中包含的对象数。
  2. 我创建一个指向方法或函数的按钮,该方法或函数使标签包含我希望它包含的信息,例如。得到() 来自入境箱的东西。
  3. 该函数然后向计数器变量添加一个条目。
  4. 然后我创建一个指向破坏最后一个标签的方法或函数的按钮,我使用计数器变量作为索引来知道 什么标签要毁灭。
  5. 然后我从计数器变量
  6. 中减去一个

    我使用字典来保持我的标签和其他小部件的顺序,例如通过使用计数器变量作为键。

    示例:

    from tkinter import *
    
    class MyEvent("something tkinter"):
        def __init__(self, parent):
    
            "here you need some tkinter code to make a frame or something to put your widgets in"
    
            self.mycounter = 0
            self.myEventLabel = {}
            addButton = Button(parent, text="add event", command=addEvent).pack()
            destroyButton = Button(parent, text="remove last event",          command=removeEvent).pack()
    
        def addEvent(self):
            self.myEventLabel[self.mycounter] = Label("Here goes the options you want)
            self.mycounter+=1
    
        def removeEvent(self):
            self.mycounter-=1
            self.myEventLabel[self.mycounter].destroy()
    

    希望这有所帮助,如果我错过了重点,那么在我的辩护中,我不是程序员,只是需要使用编程作为达到目的的手段。同样,Sentdex的视频涵盖了很多tkinter,请查看它们。

答案 1 :(得分:0)

您必须保存类实例才能将其删除。下面,addEvent()已被更改为从调用类中捕获返回,并且该实例附加到按钮,因此按钮知道要销毁哪个实例。如果所有代码都包含在类中,但是我遵循您在上面发布的代码,这可能只是一个简单的例子。

from Tkinter import *
from functools import partial

class agendaEvent:
    def __init__(self, master):
        self.frame = Frame(master, padx=10, pady=10)
        self.frame.grid()
        self.name = Entry(self.frame)
        self.name.grid(row=1, column=0)
        self.time = Entry(self.frame, width=10)
        self.time.grid(row=1, column=1, padx=5)
        self.label1 = Label(self.frame, text="Event Name")
        self.label1.grid(row=0, column=0)
        self.label2 = Label(self.frame, text="Minutes")
        self.label2.grid(row=0, column=1)

def addEvent(master):
        this_instance=agendaEvent(master) 
        ## add the button to the frame created by this function call
        ## and not to the root, so it also is destroyed
        rem = Button(this_instance.frame, text="Remove", bg="lightblue",
                     command=partial(remove_class, this_instance))
        rem.grid(row=6, column=0)

def remove_class(instance):
    ## destroys the frame created by the instance
    ## i.e. self.frame in agendaEvent
    instance.frame.destroy()  
    instance=""          ## reassigns "instance" so the class is garbage collected

root = Tk()

addEventButton = Button(root, text="Add Event", command=partial(addEvent, root))
addEventButton.grid(row=5, column=0)

Button(root, text="Exit", bg="orange", command=root.quit).grid(row=99, column=0)

root.mainloop()

答案 2 :(得分:0)

如下所示更改课程将修复您当前获得的错误。这是因为传递给command构造函数的Button关键字参数指定的处理程序总是在没有任何参数的情况下被调用。使用lambda函数修复它会暴露另一个问题,即您已将Button实例和要将其关联的方法命名为同一事物 - remove - 所以我将其重命名为remove_button

from Tkinter import *

class agendaEvent:
    def __init__(self, master):
        self.frame = Frame(master, padx=10, pady=10)
        self.frame.pack(side=TOP)
        self.name = Entry(self.frame)
        self.name.grid(row=1, column=0)
        self.time = Entry(self.frame, width=10)
        self.time.grid(row=1, column=1, padx=5)
        self.label1 = Label(self.frame, text="Event Name")
        self.label1.grid(row=0, column=0)
        self.label2 = Label(self.frame, text="Minutes")
        self.label2.grid(row=0, column=1)
        self.remove_button = Button(self.frame, text="Remove",
                                    command=lambda: self.remove())
        self.remove_button.grid(row=1, column=3)

    def remove(self):  # by convention the first argument to a class
        del self       # method is usually named "self"