TKinter Destroy Question

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Rob

    TKinter Destroy Question

    My first GUI so be gentle...

    When I start my program I call a class that runs the initial window. While
    in this class if a certain button is pressed it calls a function outside the
    class. This function then initially calls another function to
    "root.destroy() ". Basically I want the current window gone so the function I
    just called can open it's own window. The problem I'm stuck with is that
    once this function is done and I need to close the new window to go to the
    next window i again call the function which performs the "root.destroy() ".
    When I try to call it a second time it tells me:

    TclError: can't invoke "destroy" command: application has been destroyed

    How can it already be destroyed if I opened a new window in my function?
    Should I slip in somewhere a new "root.mainloop( )" statment? It seems when I
    try this I get some weird results (Every command after the new
    root.mainloop() nothing happens, no buttons drawn, nothing). Is there an
    easier way to clear windows than to use the root.destroy? I've basically run
    into a nice brick wall...

    Thanks for the help!
    Rob


  • Eric Brunel

    #2
    Re: TKinter Destroy Question

    Rob wrote:[color=blue]
    > My first GUI so be gentle...
    >
    > When I start my program I call a class that runs the initial window. While
    > in this class if a certain button is pressed it calls a function outside the
    > class. This function then initially calls another function to
    > "root.destroy() ". Basically I want the current window gone so the function I
    > just called can open it's own window. The problem I'm stuck with is that
    > once this function is done and I need to close the new window to go to the
    > next window i again call the function which performs the "root.destroy() ".
    > When I try to call it a second time it tells me:
    >
    > TclError: can't invoke "destroy" command: application has been destroyed
    >
    > How can it already be destroyed if I opened a new window in my function?
    > Should I slip in somewhere a new "root.mainloop( )" statment? It seems when I
    > try this I get some weird results (Every command after the new
    > root.mainloop() nothing happens, no buttons drawn, nothing). Is there an
    > easier way to clear windows than to use the root.destroy? I've basically run
    > into a nice brick wall...[/color]

    Destroying the root window in a Tkinter application actually means destroying
    the whole application, not only the root window. The root window is the main
    window for the application; it is the first to pop up and must be the last to
    go. If I understand correctly, your application does not have an actual main
    window: if a second window is opened from the initial window, closing the
    initial window should not quit the application. Am I right?

    If I am, the way to do that with Tkinter (or tcl/tk) is to create a fake root
    window and hide it. This window will only be used to quit the application when
    the last window is closed:

    ----------------------------------------------------------
    from Tkinter import *

    ## Create main window
    root = Tk()
    ## Hide it
    root.withdraw()

    ## List of windows currently opened
    windows = []

    ## Function to create a new window
    def newWindow():
    ## Create window
    wdw = Toplevel()
    ## Button in window to create another new window
    Button(wdw, text='New window', command=newWind ow).pack()
    ## Remember window in list of opened ones
    windows.append( wdw)
    ## When the user asks to close the window, call function closeWindow on it
    wdw.protocol('W M_DELETE_WINDOW ', lambda wdw=wdw: closeWindow(wdw ))

    ## Function called when a window's close button is clicked
    def closeWindow(wdw ):
    ## Actually close the window
    wdw.destroy()
    ## Remove window from list of opened ones
    if wdw in windows: windows.remove( wdw)
    ## If no more opened windows, quit application
    if not windows: root.quit()

    ## Create first window in application
    newWindow()

    ## Run appliction
    root.mainloop()
    ----------------------------------------------------------

    Run the script and create a few windows. You'll see that you can close any
    window you want in any order: the application quits only when the last window is
    closed.

    HTH
    --
    - Eric Brunel <eric dot brunel at pragmadev dot com> -
    PragmaDev : Real Time Software Development Tools - http://www.pragmadev.com

    Comment

    • Martin Franklin

      #3
      Re: TKinter Destroy Question

      On Thu, 2003-11-20 at 04:59, Rob wrote:[color=blue]
      > My first GUI so be gentle...
      >
      > When I start my program I call a class that runs the initial window. While
      > in this class if a certain button is pressed it calls a function outside the
      > class. This function then initially calls another function to
      > "root.destroy() ". Basically I want the current window gone so the function I
      > just called can open it's own window. The problem I'm stuck with is that
      > once this function is done and I need to close the new window to go to the
      > next window i again call the function which performs the "root.destroy() ".
      > When I try to call it a second time it tells me:
      >
      > TclError: can't invoke "destroy" command: application has been destroyed
      >[/color]


      When you destroy a window it's gone! so can't be destroyed again.....
      Without an example of what you are doing it's difficult to help but.
      You could call withdraw() method on root this will unmap it from the
      screen (but not destroy it) However why are you calling destroy on root
      twice? Perhaps you mean to call destroy on the old window when you
      create a new one (like a Wizard)


      e.g (untested...)

      root=Tk()

      def createNext():
      nextWindow = Toplevel()
      nextWindow.titl e("Next Window")
      b = Button(root, text="Create Next Window", command=createN ext)
      b.pack()
      root.withdraw()


      root.title("The Main Root Window")
      b = Button(root, text="Create Next Window", command=createN ext)
      b.pack()
      root.mainloop()


      The problem here is you are not getting rid of the previous window when
      the Next button is pressed just root!


      Perhaps a better example would be:-


      class MyApplication(T k):
      def __init__(self):
      Tk.__init__(sel f)
      self.title("Mai n Application Window")
      self.prevWindow = self
      self.windowCoun t = 1
      b = Button(self, text="Next", command=self.ne xtWindow)
      b.pack()

      def nextWindow(self ):
      window = Toplevel()
      self.windowCoun t = self.windowCoun t + 1
      window.title("N ext Window %d" %self.windowCou nt)
      b = Button(window, text="Next", command=self.ne xtWindow)
      b.pack()
      self.prevWindow .withdraw()
      self.prevWindow = window




      app = MyApplication()
      app.mainloop()


      However this will never finish! to close the whole application the
      app.quit() method must be called..... or if it's inside the class
      definition self.quit()

      Basically explain what you want with some example code and we can help

      Regards
      Martin


      --
      Martin Franklin <mfranklin1@gat wick.westerngec o.slb.com>


      Comment

      Working...