Tkinter programming problem

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

    Tkinter programming problem

    Could someone help me out with these few lines of code: I would like
    to know why the Quit button in this application removes the buttons
    and causes "Quitting" to be printed, but does not close the outer
    frame.

    Andrew.


    # Demonstration TK interface Windows application
    # Runs ok from within IDLE
    #
    from Tkinter import *

    class CommonStuff: # to get common access to variables and functions
    def __init__(cself, frame):
    cself.frame = frame

    def say_hi(cself):
    print "Hello all"


    class MyWidgets(Frame , CommonStuff):
    def __init__(wself, CS):
    Frame.__init__( wself, CS.frame)
    wself.quitbutto n = Button(wself)
    wself.quitbutto n["text"] = "Quit"
    wself.quitbutto n["fg"] = "red"
    wself.quitbutto n["command"] = wself.destroy

    wself.quitbutto n.pack({"side": "left"})

    wself.hi_there = Button(wself)
    wself.hi_there["text"] = "Hello",
    wself.hi_there["command"] = CS.say_hi

    wself.hi_there. pack({"side": "left"})


    class Application:
    def __init__(self, master):
    self.frame=Fram e(master)
    CS = CommonStuff(sel f.frame)

    displayedwidget =MyWidgets(CS)
    displayedwidget .grid(row=0, column=0)
    self.frame.grid (row=0, column=0)
    self.frame.colu mnconfigure(0)
    displayedwidget .bind("<Destroy >", self.quit)
    self.frame.upda te()

    def quit(self, event):
    print"Quitting. .."
    self.frame.dest roy # Destroy frame and all children


    root = Tk()
    mainWin = Application(roo t)
    root.wait_windo w(mainWin.frame )
  • Eric Brunel

    #2
    Re: Tkinter programming problem

    Andrew Gregory wrote:[color=blue]
    > Could someone help me out with these few lines of code: I would like
    > to know why the Quit button in this application removes the buttons
    > and causes "Quitting" to be printed, but does not close the outer
    > frame.
    >
    > Andrew.
    >
    >
    > # Demonstration TK interface Windows application
    > # Runs ok from within IDLE
    > #
    > from Tkinter import *
    >
    > class CommonStuff: # to get common access to variables and functions
    > def __init__(cself, frame):
    > cself.frame = frame[/color]

    It is a Bad Idea to give the first parameter of a method any other name than
    "self"... Checking tools like PyChecker will complain if you do that, and your
    programs will be harder to read for anyone else doing Python...
    [color=blue]
    > def say_hi(cself):
    > print "Hello all"
    >
    >
    > class MyWidgets(Frame , CommonStuff):
    > def __init__(wself, CS):
    > Frame.__init__( wself, CS.frame)[/color]

    Where have you found this type of Tkinter object initialization? Apparently,
    there are weird style guides lying around somewhere... You can rewrite all of this:
    [color=blue]
    > wself.quitbutto n = Button(wself)
    > wself.quitbutto n["text"] = "Quit"
    > wself.quitbutto n["fg"] = "red"
    > wself.quitbutto n["command"] = wself.destroy
    >
    > wself.quitbutto n.pack({"side": "left"})[/color]

    like that:

    wself.quitbutto n = Button(wself, text='Quit', fg='red', command=wself.d estroy)
    wself.quitbutto n.pack(side=LEF T)

    This is the most common way to do things. BTW, since you never do anything to
    the buttons themselves ouside this method, there's no need at all to store them
    in attributes. So you can just do:

    quitbutton = Button(wself, text='Quit', fg='red', command=wself.d estroy)
    quitbutton.pack (side=LEFT)

    or even:

    Button(wself, text='Quit', fg='red', command=wself.d estroy).pack(si de=LEFT)
    [color=blue]
    > wself.hi_there = Button(wself)
    > wself.hi_there["text"] = "Hello",
    > wself.hi_there["command"] = CS.say_hi
    >
    > wself.hi_there. pack({"side": "left"})[/color]

    Same here:

    wself.hi_there = Button(wself, text="Hello", command=CS.say_ hi)
    wself.hi_there. pack(side=LEFT)

    or:

    hi_there = Button(wself, text="Hello", command=CS.say_ hi)
    hi_there.pack(s ide=LEFT)

    or even:

    Button(wself, text="Hello", command=CS.say_ hi).pack(side=L EFT)
    [color=blue]
    >
    > class Application:
    > def __init__(self, master):
    > self.frame=Fram e(master)
    > CS = CommonStuff(sel f.frame)
    >
    > displayedwidget =MyWidgets(CS)
    > displayedwidget .grid(row=0, column=0)
    > self.frame.grid (row=0, column=0)
    > self.frame.colu mnconfigure(0)[/color]

    This statement is a no-op: you say you'll configure the column n#0 of
    self.frame, but you do not give any features for the column. What are you trying
    to do?
    [color=blue]
    > displayedwidget .bind("<Destroy >", self.quit)
    > self.frame.upda te()
    >
    > def quit(self, event):
    > print"Quitting. .."
    > self.frame.dest roy # Destroy frame and all children[/color]

    Compare this line to the last in the __init__ method just above. To call the
    update method on self.frame, you did self.frame.upda te(). So to call the destroy
    method on self.frame, you must do self.frame.dest roy(). self.frame.dest roy
    merely returns the destroy method of the self.frame object, but doesn't do
    anything with it.
    [color=blue]
    > root = Tk()
    > mainWin = Application(roo t)
    > root.wait_windo w(mainWin.frame )[/color]

    I don't know if this works, but I know it's not the usual way to run a Tkinter
    application. You'd better replace the last line by:

    root.mainloop()

    HTH

    --
    - Eric Brunel <eric.brunel@pr agmadev.com> -
    PragmaDev : Real Time Software Development Tools - http://www.pragmadev.com

    Comment

    • Andrew Gregory

      #3
      Re: Tkinter programming problem

      Many thanks for such a comprehensive answer.

      Altered root.wait_windo w(mainWin.frame ) to root.mainloop()
      and found that it runs and closes ok within IDLE. I seem to remember
      having crashes on closing within IDLE before.

      I did try self.frame.dest roy as the function
      self.frame.dest roy(), but the Quit button still didn't work. The
      application can be closed via the window corner X, but I'm still
      puzzled as to why it does not respond to Quit.

      Any more suggestions?


      Updated code below, Andrew.



      # Demonstration TK interface Windows application
      # Runs ok from within IDLE
      #
      from Tkinter import *

      class CommonStuff: # to get common access to variables and functions
      def __init__(self, frame):
      self.frame = frame

      def say_hi(self):
      print "Hello all"


      class MyWidgets(Frame , CommonStuff):
      def __init__(self, CS):
      Frame.__init__( self, CS.frame)
      self.quitbutton = Button(self, text='Quit', fg='red',
      command=self.de stroy)
      self.quitbutton .pack(side=LEFT )
      self.hi_there = Button(self, text='Hello', command=CS.say_ hi)
      self.hi_there.p ack(side=LEFT)


      class Application:
      def __init__(self, master):
      self.frame=Fram e(master)
      CS = CommonStuff(sel f.frame)

      displayedwidget =MyWidgets(CS)
      displayedwidget .grid(row=0, column=0)
      self.frame.grid (row=0, column=0)
      displayedwidget .bind("<Destroy >", self.quit)
      self.frame.upda te()

      def quit(self, event):
      print"Quitting. .."
      self.frame.dest roy() # Destroy frame and all children


      root = Tk()
      mainWin = Application(roo t)
      root.mainloop()

      Comment

      • klappnase

        #4
        Re: Tkinter programming problem

        >[color=blue]
        >
        > # Demonstration TK interface Windows application
        > # Runs ok from within IDLE
        > #
        > from Tkinter import *
        >
        > class CommonStuff: # to get common access to variables and functions
        > def __init__(self, frame):
        > self.frame = frame
        >
        > def say_hi(self):
        > print "Hello all"
        >
        >
        > class MyWidgets(Frame , CommonStuff):
        > def __init__(self, CS):
        > Frame.__init__( self, CS.frame)
        > self.quitbutton = Button(self, text='Quit', fg='red',
        > command=self.de stroy)
        > self.quitbutton .pack(side=LEFT )
        > self.hi_there = Button(self, text='Hello', command=CS.say_ hi)
        > self.hi_there.p ack(side=LEFT)
        >
        >
        > class Application:
        > def __init__(self, master):
        > self.frame=Fram e(master)
        > CS = CommonStuff(sel f.frame)
        >
        > displayedwidget =MyWidgets(CS)
        > displayedwidget .grid(row=0, column=0)
        > self.frame.grid (row=0, column=0)
        > displayedwidget .bind("<Destroy >", self.quit)
        > self.frame.upda te()
        >
        > def quit(self, event):
        > print"Quitting. .."
        > self.frame.dest roy() # Destroy frame and all children
        >
        >
        > root = Tk()
        > mainWin = Application(roo t)
        > root.mainloop()[/color]

        I think you could have it easier, if you just want to exit you
        application with the quit button:

        class MyWidgets(Frame , CommonStuff):
        def __init__(self, CS):
        Frame.__init__( self, CS.frame)
        self.quitbutton = Button(self, text='Quit', fg='red',
        command=self.qu it)
        self.quitbutton .pack(side=LEFT )
        self.hi_there = Button(self, text='Hello', command=CS.say_ hi)
        self.hi_there.p ack(side=LEFT)

        def quit(self):
        print "Quitting.. ."
        sys.exit(0)

        If you want to run it from within the interpreter (I am not sure if it
        is that what you are trying) the following might work too:

        class Application:
        def __init__(self, master):
        self.frame=Fram e(master)
        CS = CommonStuff(sel f.frame)

        displayedwidget =MyWidgets(CS)
        displayedwidget .grid(row=0, column=0)
        self.frame.grid (row=0, column=0)
        displayedwidget .bind("<Destroy >", self.quit)
        self.frame.upda te()

        self.master = master

        def quit(self, event):
        print"Quitting. .."
        self.master.des troy() # Destroy root window

        However I would recommend to store the code in a file and then run the
        file.
        I am sorry that I cannot give you more detailed advice, but I am still
        a beginner, too. I hope this helped anyway.

        Good luck!

        Michael

        Comment

        • klappnase

          #5
          Re: Tkinter programming problem

          Eric Brunel <eric.brunel@pr agmadev.com> wrote in message news:<bgnmjv$om [email protected] .fr>...
          [color=blue]
          > This may also work, but the most common way is the one I describe above. If you
          > want to do it here, you can do:
          >
          > def quit(self, event):
          > print "Quitting.. ."
          > self.master.qui t()
          >
          > AFAIK, all Tkinter widgets have a quit method that will quit the Tk mainloop.
          >
          > HTH[/color]

          I think Tkinter's quit() method will not work while running from
          within the interpreter, because there is no mainloop. I think you will
          have to destroy() there.

          Best regards

          Michael

          Comment

          • Eric Brunel

            #6
            Re: Tkinter programming problem

            furliz wrote:[color=blue][color=green]
            >> I did try self.frame.dest roy as the function self.frame.dest roy(),
            >> but the Quit button still didn't work. The
            >> application can be closed via the window corner X, but I'm still
            >> puzzled as to why it does not respond to Quit.
            >>
            >> Any more suggestions?[/color]
            >
            >
            > why don't use 'sys.exit(0)' as command?
            > Ex:
            > quitButton = Button(root,tex t="Quit",comman d=sys.exit(0))[/color]

            Don't do that!! Written like above, sys.exit(0) will be called when the button
            is *created*, not when it is pressed! If you want to do that, write:

            quitButton = Button(root, text='Quit', command=lambda: sys.exit(0))
            --
            - Eric Brunel <eric.brunel@pr agmadev.com> -
            PragmaDev : Real Time Software Development Tools - http://www.pragmadev.com

            Comment

            Working...