1
votes

I am a python beginner. Try to make a new button to close the window. I got the error message:

Exception in Tkinter callback Traceback (most recent call last): File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 1536, in call return self.func(*args) File "tk_cp_successful.py", line 138, in buttonPushed self.root.destroy() File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/Tkinter.py", line 1859, in destroy self.tk.call('destroy', self._w) TclError: can't invoke "destroy" command: application has been destroyed

class LoginPage(tk.Frame):
   def __init__(self, parent, controller):
      self.controller = controller
      self.root = tk.Tk()
      global entry_1
      global entry_2
      tk.Frame.__init__(self, parent)
      label = tk.Label(self, text="Welcome to VISA Login Page",fg="blue")
      label.pack(pady=10,padx=10)

      label_1 = Label(self, text="Username")
      label_1.pack()
      label_2 = Label(self, text="Password")
      label_2.pack()
      entry_1 = Entry(self)
      entry_1.pack()
      entry_2 = Entry(self, show="*")
      entry_2.pack()
      label_1.grid(row=0, sticky=E)
      label_1.pack()
      label_2.grid(row=1, sticky=E)
      label_2.pack()
      entry_1.grid(row=0, column=1)
      entry_1.pack()
      entry_2.grid(row=1, column=1)
      entry_2.pack()
      checkbox = Checkbutton(self, text="Keep me logged in")

      checkbox.grid(columnspan=2)
      checkbox.pack()
      logbtn = Button(self, text="Login", command = self._login_btn_clickked)
      logbtn.grid(columnspan=2)
      logbtn.pack()
      myButton = Button(self, text="Exit",command = self.buttonPushed)
      myButton.pack()

  def buttonPushed(self):
      self.root.destroy()

  def _login_btn_clickked(self):
      #print("Clicked")
      username = entry_1.get()
      password = entry_2.get()

      #print(username, password)

      if username == "test" and password == "test":
          #box.showinfo("Login info", "Welcome Tester")
          button1 = ttk.Button(self, text="Please click, Welcome to login!!!",
                     command=lambda: self.controller.show_frame(StartPage))
          button1.pack()
      else:
          box.showerror("Login failed", "Incorrect username")
6
I've never seen this: logbtn.grid(columnspan=2); logbtn.pack(), that is, "griding" a widget and immediately after "packing" it. I don't know what is the real effect, but I almost pretty sure that's not the "correct" way of doing it. - nbro
thank you for the helps. I can run on it without destroy. all work fine. once I run buttonPushed, it get error. feel root is global, it cannot use from this class --------.self.root.destroy() - jack

6 Answers

3
votes

There are many problems with your code

  1. Indentation errors
  2. Mixing grid() and pack()
  3. Do you import tkinter as tk or from tkinter import *, i.e.
    self.root = tk.Tk() (import as tk) or
    label_1 = Label(self, text="Username") (from tkinter import *)
  4. No mainloop in program
  5. Use of global in a class is not necessary and poor style

In any case, the following modified code runs so hopefully it will help.

import sys
if sys.version_info[0] < 3:
    import Tkinter as tk     ## Python 2.x
else:
    import tkinter as tk     ## Python 3.x

class LoginPage():
   def __init__(self):
      self.root=tk.Tk()
      label = tk.Label(self.root, text="Welcome to VISA Login Page",fg="blue")
      label.grid(row=0)

      label_1 = tk.Label(self.root, text="Username")
      label_2 = tk.Label(self.root, text="Password")
      self.entry_1 = tk.Entry(self.root)
      self.entry_2 = tk.Entry(self.root, show="*")
      label_1.grid(row=1, sticky="e")
      label_2.grid(row=2, sticky="e")
      self.entry_1.grid(row=1, column=1)
      self.entry_2.grid(row=2, column=1)

      ## doesn't do anything at this time
      ##checkbox = tk.Checkbutton(self.root, text="Keep me logged in")
      ##checkbox.grid(row=3, columnspan=2)

      logbtn = tk.Button(self.root, text="Login", command = self._login_btn_clickked)
      logbtn.grid(row=9, columnspan=2)
      myButton = tk.Button(self.root, text="Exit",command = self.buttonPushed)
      myButton.grid(row=10)

      self.root.mainloop()

   def buttonPushed(self):
      self.root.destroy()

   def _login_btn_clickked(self):
      #print("Clicked")
      username = self.entry_1.get()
      password = self.entry_2.get()

      #print(username, password)

      if username == "test" and password == "test":
          print "OK login"
          #box.showinfo("Login info", "Welcome Tester")
          #button1 = ttk.Button(self.root, text="Please click, Welcome to login!!!",
          #           command=lambda: self.controller.show_frame(StartPage))
          #button1.pack()
      else:
          #box.showerror("Login failed", "Incorrect username")
          print "Error"

LP=LoginPage()
2
votes

Ignoring all of the other problems with your code, I had the same problem the other day. When you call self.root.destroy(), Tkinter will exit the root.mainloop. Then after the place where you call root.mainloop you probably have a call to root.destroy. This means you are trying to destroy twice, which is what is causing the error. One way to deal with this is to let the Exception pass silently (though in general this is not good practice):

try:
    root.destroy()
except:
    pass

I may be wrong, but this is the only thing I can imagine is causing this error.

0
votes

If applicable, root.quit() might fix the error.

0
votes

This error usually occurs when you have more than 2 mainloops. Do nothing more than:

import sys

and then create a button to exit:

B=tk.Button(self.root,text="quit",command=lambda:sys.exit())
B.grid()
0
votes

you need to destroy the def as they will keep repeating. Use "your def".destroy() to prevent this error from happening. I had the same issue. it was one of the def causing it for me and destroying this def in an if statement solved my issue

0
votes

If you mistakenly destroy a root window that is already destroyed or not created yet then this kind of error occurs