Search code examples
pythontkinterattributeerror

AttributeError: application instance has no attribute 'after'


Could someone please advise why I am getting the following error:

Exception in Tkinter callback
Traceback (most recent call last):
  File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1437, in __call__
    return self.func(*args)
  File "./transrecv.py", line 137, in Enter
    self.after(tTimer, self.Enter)
AttributeError: application instance has no attribute 'after'

I am trying to right the class so that it can either repeat the command or only do it once based on the information input by the user.

Code:

class application:

    def __init__(self,window):
        """Initialize the Application """
        self.IDbox = tk.Entry(window, width = 5)
        self.IDbox.pack(side="left", expand=True)
        self.IDbox.insert(0,"ID")

        self.msgTypeBox = tk.Entry(window)
        self.msgTypeBox.pack(side="left", expand=True)
        self.msgTypeBox.insert(0,"Message Type")

        self.canTypeBox = tk.Entry(window)
        self.canTypeBox.pack(side="left", expand=True)
        self.canTypeBox.insert(0,"Can Type")

        self.tData0Box = tk.Entry(window, width = 5)
        self.tData0Box.pack(side="left", expand=True)
        self.tData0Box.insert(0,"Data0")

        self.tData1Box = tk.Entry(window, width = 5)
        self.tData1Box.pack(side="left", expand=True)
        self.tData1Box.insert(0,"Data1")

        self.tData2Box = tk.Entry(window, width = 5)
        self.tData2Box.pack(side="left", expand=True)
        self.tData2Box.insert(0,"Data2")

        self.tData3Box = tk.Entry(window, width = 5)
        self.tData3Box.pack(side="left", expand=True)
        self.tData3Box.insert(0,"Data3")

        self.tData4Box = tk.Entry(window, width = 5)
        self.tData4Box.pack(side="left", expand=True)
        self.tData4Box.insert(0,"Data4")

        self.tData5Box = tk.Entry(window, width = 5)
        self.tData5Box.pack(side="left", expand=True)
        self.tData5Box.insert(0,"Data5")

        self.tData6Box = tk.Entry(window, width = 5)
        self.tData6Box.pack(side="left", expand=True)
        self.tData6Box.insert(0,"Data6")

        self.tData7Box = tk.Entry(window, width = 5)
        self.tData7Box.pack(side="left", expand=True)
        self.tData7Box.insert(0,"Data7")

        self.tTimerBox = tk.Entry(window, width = 5)
        self.tTimerBox.pack(side="left", expand=True)
        self.tTimerBox.insert(0,"0")

        self.TranButton = tk.Button(window,
                                    text="Transmit",
                                    command = self.Enter)
        self.TranButton.pack(side="bottom")

    def Enter(self):
        """ Someone Pressed Enter """
        canID = self.IDbox.get()
        msgType = self.msgTypeBox.get()
        canType = self.canTypeBox.get()
        DLC = 8
        tData0 = self.tData0Box.get()
        tData1 = self.tData1Box.get()
        tData2 = self.tData2Box.get()
        tData3 = self.tData3Box.get()
        tData4 = self.tData4Box.get()
        tData5 = self.tData5Box.get()
        tData6 = self.tData6Box.get()
        tData7 = self.tData7Box.get()
        tTimer = self.tTimerBox.get()
        print("You tranmitted >> %s %s %s %d %s %s %s %s %s %s %s %s " %
             (msgType, canType, canID, DLC,  tData0, tData1,
               tData2, tData3, tData4, tData5, tData6, tData7))
        if int(tTimer) <= 0:
            system('echo "%s %s 0x%s %d 0x%s 0x%s 0x%s 0x%s 0x%s 0x%s 0x%s 0x%s" >/dev/pcan33' %
                    (msgType, canType, canID, DLC, tData0, tData1,
                     tData2, tData3, tData4, tData5, tData6, tData7))
        else:
            self.after(tTimer, self.Enter)

 root = tk.Tk()

 myapp = application(root)
 root.mainloop()

Solution

  • Like the error says, your class has no attribute after. after is a method of Tkinter widgets, and your class doesn't inherit from any widgets.

    I suggest fixing your code to be like this:

    class application:

    def __init__(self,window):
        ...
        self.window = window
        ...
    def Enter(self):
        ...
        if int(tTimer) <= 0:
            ...
        else:
            self.window.after(tTimer, self.Enter)
    

    Another solution is to create your own after method that calls self.window.after.