Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #21025 > unrolled thread

Is it necessary to call Tk() when writing a GUI app with Tkinter?

Started byJohn Salerno <johnjsal@gmail.com>
First post2012-02-28 21:06 -0800
Last post2012-03-03 20:27 -0800
Articles 12 on this page of 32 — 7 participants

Back to article view | Back to comp.lang.python


Contents

  Is it necessary to call Tk() when writing a GUI app with Tkinter? John Salerno <johnjsal@gmail.com> - 2012-02-28 21:06 -0800
    Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? Rick Johnson <rantingrickjohnson@gmail.com> - 2012-02-29 06:24 -0800
      Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? Terry Reedy <tjreedy@udel.edu> - 2012-02-29 19:17 -0500
        Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? Rick Johnson <rantingrickjohnson@gmail.com> - 2012-02-29 19:22 -0800
          Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? Terry Reedy <tjreedy@udel.edu> - 2012-03-01 00:24 -0500
            Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? Rick Johnson <rantingrickjohnson@gmail.com> - 2012-03-01 18:49 -0800
              Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? Rick Johnson <rantingrickjohnson@gmail.com> - 2012-03-01 19:02 -0800
              Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? Terry Reedy <tjreedy@udel.edu> - 2012-03-01 22:43 -0500
              Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? Terry Reedy <tjreedy@udel.edu> - 2012-03-02 15:19 -0500
                Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? Mel Wilson <mwilson@the-wire.com> - 2012-03-02 15:52 -0500
              Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? "Russell E. Owen" <rowen@uw.edu> - 2012-03-05 11:45 -0800
          Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? John Salerno <johnjsal@gmail.com> - 2012-02-29 21:40 -0800
            Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? Rick Johnson <rantingrickjohnson@gmail.com> - 2012-03-01 18:53 -0800
              Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? Mark Roseman <mark@markroseman.com> - 2012-03-02 10:57 -0700
                Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? John Salerno <johnjsal@gmail.com> - 2012-03-02 10:53 -0800
      Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? John Salerno <johnjsal@gmail.com> - 2012-02-29 20:41 -0800
        Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? Terry Reedy <tjreedy@udel.edu> - 2012-03-01 00:40 -0500
          Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? John Salerno <johnjsal@gmail.com> - 2012-02-29 21:45 -0800
            Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? John Salerno <johnjsal@gmail.com> - 2012-02-29 22:14 -0800
              Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? Rick Johnson <rantingrickjohnson@gmail.com> - 2012-03-01 18:55 -0800
            Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? John Salerno <johnjsal@gmail.com> - 2012-02-29 22:14 -0800
          Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? John Salerno <johnjsal@gmail.com> - 2012-02-29 21:45 -0800
          Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? John Salerno <johnjsal@gmail.com> - 2012-02-29 22:41 -0800
          Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? John Salerno <johnjsal@gmail.com> - 2012-02-29 22:41 -0800
            Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2012-03-01 07:38 +0000
              Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? John Salerno <johnjsal@gmail.com> - 2012-02-29 23:58 -0800
        Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? Rick Johnson <rantingrickjohnson@gmail.com> - 2012-03-01 18:35 -0800
          Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? John Salerno <johnjsal@gmail.com> - 2012-03-01 19:15 -0800
            Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? Rick Johnson <rantingrickjohnson@gmail.com> - 2012-03-01 19:19 -0800
              Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? John Salerno <johnjsal@gmail.com> - 2012-03-01 21:22 -0800
          Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? John Salerno <johnjsal@gmail.com> - 2012-03-02 14:16 -0800
            Re: Is it necessary to call Tk() when writing a GUI app with Tkinter? Rick Johnson <rantingrickjohnson@gmail.com> - 2012-03-03 20:27 -0800

Page 2 of 2 — ← Prev page 1 [2]


#21077

FromJohn Salerno <johnjsal@gmail.com>
Date2012-02-29 22:14 -0800
Message-ID<mailman.317.1330582484.3037.python-list@python.org>
In reply to#21074
> What exactly is the purpose of doing that? Does Tk do some extra work that a simple call to Frame won't do?

More specifically, what is the benefit of doing:

root = tk.Tk()
app = Application(master=root)
app.mainloop()

as opposed to:

app = Application()
app.mainloop()

Also, in the first example, what is the difference between calling app.mainloop() and root.mainloop()? They both seemed to work when I ran them.

[toc] | [prev] | [next] | [standalone]


#21075

FromJohn Salerno <johnjsal@gmail.com>
Date2012-02-29 21:45 -0800
Message-ID<mailman.316.1330580737.3037.python-list@python.org>
In reply to#21072
On Wednesday, February 29, 2012 11:40:45 PM UTC-6, Terry Reedy wrote:
> On 2/29/2012 11:41 PM, John Salerno wrote:
> 
> > window? If you only want the Windows "X" button to close the window,
> > then is it okay to leave out any call to destroy()?
> 
> Yes. You must leave it out.
> 
> > the latter, then where in the code do you put the call to destroy so
> > it won't conflict with the user closing the window with the X
> > button?
> 
> See my other post of a few minutes ago for an example that now works.
> 
> -- 
> Terry Jan Reedy

When you suggested I create the root frame explicitly, you mean create a Tk object explicitly, as in your example, and then pass that as an argument to the Frame instance?

What exactly is the purpose of doing that? Does Tk do some extra work that a simple call to Frame won't do?

[toc] | [prev] | [next] | [standalone]


#21081

FromJohn Salerno <johnjsal@gmail.com>
Date2012-02-29 22:41 -0800
Message-ID<mailman.319.1330584122.3037.python-list@python.org>
In reply to#21072
> Yes. You must leave it out.

Now I'm reading a Tkinter reference at
http://infohost.nmt.edu/tcc/help/pubs/tkinter/minimal-app.html
and it has this example:


#!/usr/local/bin/python     
from Tkinter import *       

class Application(Frame):              
    def __init__(self, master=None):
        Frame.__init__(self, master)   
        self.grid()                    
        self.createWidgets()

    def createWidgets(self):
        self.quitButton = Button ( self, text='Quit',
            command=self.quit )        
        self.quitButton.grid()         

app = Application()                    
app.master.title("Sample application") 
app.mainloop()


Is this just outdated? I don't understand why it uses quit() instead of destroy(). When I try this in IDLE, quit() just causes the application to hang (I assume because it ends the mainloop without actually closing the application). Or is this just a problem when using IDLE?

If the latter, which is preferable, quit or destroy?

[toc] | [prev] | [next] | [standalone]


#21082

FromJohn Salerno <johnjsal@gmail.com>
Date2012-02-29 22:41 -0800
Message-ID<23675630.870.1330584114032.JavaMail.geo-discussion-forums@ynjc20>
In reply to#21072
> Yes. You must leave it out.

Now I'm reading a Tkinter reference at
http://infohost.nmt.edu/tcc/help/pubs/tkinter/minimal-app.html
and it has this example:


#!/usr/local/bin/python     
from Tkinter import *       

class Application(Frame):              
    def __init__(self, master=None):
        Frame.__init__(self, master)   
        self.grid()                    
        self.createWidgets()

    def createWidgets(self):
        self.quitButton = Button ( self, text='Quit',
            command=self.quit )        
        self.quitButton.grid()         

app = Application()                    
app.master.title("Sample application") 
app.mainloop()


Is this just outdated? I don't understand why it uses quit() instead of destroy(). When I try this in IDLE, quit() just causes the application to hang (I assume because it ends the mainloop without actually closing the application). Or is this just a problem when using IDLE?

If the latter, which is preferable, quit or destroy?

[toc] | [prev] | [next] | [standalone]


#21083

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2012-03-01 07:38 +0000
Message-ID<4f4f2760$0$11107$c3e8da3@news.astraweb.com>
In reply to#21082
On Wed, 29 Feb 2012 22:41:53 -0800, John Salerno wrote:

>> Yes. You must leave it out.
> 
> Now I'm reading a Tkinter reference at
> http://infohost.nmt.edu/tcc/help/pubs/tkinter/minimal-app.html and it
> has this example:
[...]

Could you please stop posting the same message twice? It's very annoying. 
There is no need to C.C. python-list because comp.lang.python is the 
mirror of the mailing list.


Thank you.



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#21084

FromJohn Salerno <johnjsal@gmail.com>
Date2012-02-29 23:58 -0800
Message-ID<30160611.9.1330588717114.JavaMail.geo-discussion-forums@ynbo9>
In reply to#21083
On Thursday, March 1, 2012 1:38:08 AM UTC-6, Steven D&#39;Aprano wrote:
> On Wed, 29 Feb 2012 22:41:53 -0800, John Salerno wrote:
> 
> >> Yes. You must leave it out.
> > 
> > Now I'm reading a Tkinter reference at
> > http://infohost.nmt.edu/tcc/help/pubs/tkinter/minimal-app.html and it
> > has this example:
> [...]
> 
> Could you please stop posting the same message twice? It's very annoying. 
> There is no need to C.C. python-list because comp.lang.python is the 
> mirror of the mailing list.
> 
> 
> Thank you.
> 
> 
> 
> -- 
> Steven

I'm sorry, it's unintentional. The new interface for Google Groups keeps doing weird things and makes double and triple posts. I deleted them from my end, but I guess they are still showing up for everyone else.

[toc] | [prev] | [next] | [standalone]


#21107

FromRick Johnson <rantingrickjohnson@gmail.com>
Date2012-03-01 18:35 -0800
Message-ID<daa75893-88ed-4ec0-b00d-ea104cbd47ae@f4g2000yqh.googlegroups.com>
In reply to#21066
On Feb 29, 10:41 pm, John Salerno <johnj...@gmail.com> wrote:
> I'm not sure I understand which method you are advocating. It
> sounded like you said calling Tk() explicitly is a bug.

I am saying just the opposite: Allowing the module "Tkinter" to
implicitly create a root window IF the programmer was too lazy to
create a root window himself is ridiculous, confusing, and
inconsistent; therefor it's a BUG! Observe:

INCORRECT:
 import Tkinter as tk
 b = tk.Button(master=None, text='Sloppy Coder')
 b.pack()
 b.mainloop()

CORRECT:
 import Tkinter as tk
 root = tk.Tk()
 b = tk.Button(root, text='Smart Coder')
 b.pack()
 root.mainloop()

IMO, only the widget "Tkinter.Tk" should have the method mainloop! If
you call w.mainloop() and "w" is NOT an instance of Tkinter.Tk, then
an error should be raised; I decided to raise a LazyCoderError in MY
version of the Tkinter module just to drive the point home.

> I certainly would never create widgets without first creating a
> master frame,

You really have no choice otherwise. Each and every widget requires a
parent argument (or parent=None, which will then create and use the
Tkinter._default_root; BUG!). The fact that Tkinter "magically"
creates the root window for you does not negate the fact that every
widget requires a parent. This is why i think the official version of
Tkinter is flawed. And the fix is very simple actually.

> but is creating a Frame object enough, or should I create a Tk
> object and *then* a Frame object?

No matter what, you MUST create an instance of Tkinter.Tk to be the
"root" window of your GUI application. After that, you can nest as
many frames, toplevels, and blah widgets under that root window as you
so desire. Actually you don't even need a "frame", you can pack
widgets directly into a Toplevel or Tk widget.

EXAMPLE 1: (this works, but is flawed!)
 root = tk.Tk()
 b = tk.Button(master=None, text='Sloppy Coder')
 b.pack()
 root.mainloop()

EXAMPLE 2: (This is how to write code!)
 root = tk.Tk()
 widgetframe = tk.Frame(root)
 b = tk.Button(master=None, text='Sloppy Coder')
 b.pack()
 root.mainloop()

EXAMPLE 3: (OOP style)
 class App(tk.Tk):
     def __init__(self):
         tk.Tk.__init__(self)
         # something should happen here to justify using OOP
     # or here

 class AppFrame(tk.Frame):
     def __init__(self, master, **kw):
         tk.Frame.__init__(self, master, **kw)
         self.createWidgets()

     def createWidgets(self):
         b = tk.Button(master=None, text='Push Me')
         b.pack()

 if __name__ == '__main__':
     app = App()
     frame = AppFrame(app)
     frame.pack()
     app.mainloop()


> Also, at what point do you include the destroy method in your
> program, assuming you do not have a widget that will close the
> window? If you only want the Windows "X" button to close the window,
> then is it okay to leave out any call to destroy()?

Yes. GUI destruction should (almost always) be controlled by the user.
In certain circumstances you will want to force destruction, or
intercept a users request for destruction so you can do something
first (cleanup, sanity checks, etc...).

> Or should always explicitly destroy it just as I explicitly created
> a Tk instance?

NO, you should create the root and then allow the user to decide when
to destroy the GUI. Always remember the phrase: "User Driven Events"
when coding a GUI!

> If the latter, then where in the code do you put the call to destroy
> so it won't conflict with the user closing the window with the X
> button?

In the "very special" cases where you need to destory the GUI, make
sure no code can run AFTER you destroy the root window. Whoever wrote
that example was obviously too lazy to run the code and check for
errors or subtle bugs.


[toc] | [prev] | [next] | [standalone]


#21113

FromJohn Salerno <johnjsal@gmail.com>
Date2012-03-01 19:15 -0800
Message-ID<6008330.241.1330658121340.JavaMail.geo-discussion-forums@ynlt17>
In reply to#21107
> EXAMPLE 1: (this works, but is flawed!)
>  root = tk.Tk()
>  b = tk.Button(master=None, text='Sloppy Coder')
>  b.pack()
>  root.mainloop()
> 
> EXAMPLE 2: (This is how to write code!)
>  root = tk.Tk()
>  widgetframe = tk.Frame(root)
>  b = tk.Button(master=None, text='Sloppy Coder')
>  b.pack()
>  root.mainloop()
> 
> EXAMPLE 3: (OOP style)
>  class App(tk.Tk):
>      def __init__(self):
>          tk.Tk.__init__(self)
>          # something should happen here to justify using OOP
>      # or here
> 
>  class AppFrame(tk.Frame):
>      def __init__(self, master, **kw):
>          tk.Frame.__init__(self, master, **kw)
>          self.createWidgets()
> 
>      def createWidgets(self):
>          b = tk.Button(master=None, text='Push Me')
>          b.pack()
> 
>  if __name__ == '__main__':
>      app = App()
>      frame = AppFrame(app)
>      frame.pack()
>      app.mainloop()

Why is the master argument for Button set to None? Shouldn't it be the Frame object? And shouldn't it also have self as the first argument?

[toc] | [prev] | [next] | [standalone]


#21114

FromRick Johnson <rantingrickjohnson@gmail.com>
Date2012-03-01 19:19 -0800
Message-ID<4eb739df-c642-4bbf-a155-9ed150e3acaf@s13g2000yqe.googlegroups.com>
In reply to#21113
On Mar 1, 9:15 pm, John Salerno <johnj...@gmail.com> wrote:
> > EXAMPLE 1: (this works, but is flawed!)
> >  root = tk.Tk()
> >  b = tk.Button(master=None, text='Sloppy Coder')
> >  b.pack()
> >  root.mainloop()
>
> > EXAMPLE 2: (This is how to write code!)
> >  root = tk.Tk()
> >  widgetframe = tk.Frame(root)
> >  b = tk.Button(master=None, text='Sloppy Coder')
> >  b.pack()
> >  root.mainloop()
>
> > EXAMPLE 3: (OOP style)
> >  class App(tk.Tk):
> >      def __init__(self):
> >          tk.Tk.__init__(self)
> >          # something should happen here to justify using OOP
> >      # or here
>
> >  class AppFrame(tk.Frame):
> >      def __init__(self, master, **kw):
> >          tk.Frame.__init__(self, master, **kw)
> >          self.createWidgets()
>
> >      def createWidgets(self):
> >          b = tk.Button(master=None, text='Push Me')
> >          b.pack()
>
> >  if __name__ == '__main__':
> >      app = App()
> >      frame = AppFrame(app)
> >      frame.pack()
> >      app.mainloop()
>
> Why is the master argument for Button set to None? Shouldn't it be the Frame object? And shouldn't it also have self as the first argument?

Hmm, it seems as though i am the latest victim of the "copy/paste
error"! Oh well, if you were going to absorb my teachings, you would
have absorbed them by now. I am moving on unless a new subject needs
explaining.

[toc] | [prev] | [next] | [standalone]


#21117

FromJohn Salerno <johnjsal@gmail.com>
Date2012-03-01 21:22 -0800
Message-ID<1510171.280.1330665781888.JavaMail.geo-discussion-forums@vbux23>
In reply to#21114
> Hmm, it seems as though i am the latest victim of the "copy/paste
> error"! Oh well, if you were going to absorb my teachings, you would
> have absorbed them by now. I am moving on unless a new subject needs
> explaining.

Well, I've certainly absorbed your recommendation to always create the root explicitly, but you still haven't really explained WHY. Telling me that I will eventually find out as I become more proficient isn't very helpful.

I like being explicit, so I will create the Tk option like you suggest (although I don't see the need to subclass it first), but I also like knowing WHY I do what I do, so it would help to have some reason why it's better to create the root explicitly rather than allow Tkinter to do it.

[toc] | [prev] | [next] | [standalone]


#21152

FromJohn Salerno <johnjsal@gmail.com>
Date2012-03-02 14:16 -0800
Message-ID<11188032.247.1330726606861.JavaMail.geo-discussion-forums@ynbq18>
In reply to#21107
> After that, you can nest as
> many frames, toplevels, and blah widgets under that root window as you
> so desire. Actually you don't even need a "frame", you can pack
> widgets directly into a Toplevel or Tk widget.

This is interesting. I completely understand your point about always calling (and using) the instance of Tk as the root. Given that, what is the point of creating a Frame object at all? I tried NOT doing it, like you said, and it seemed to work fine with my simple example. But is there a benefit to using a Frame object to group the widgets together? Or is it cleaner to just use the Tk object?

[toc] | [prev] | [next] | [standalone]


#21177

FromRick Johnson <rantingrickjohnson@gmail.com>
Date2012-03-03 20:27 -0800
Message-ID<cc277532-0e5a-4afe-a4a5-bd3c1c5ea994@n12g2000yqb.googlegroups.com>
In reply to#21152
On Mar 2, 4:16 pm, John Salerno <johnj...@gmail.com> wrote:
> what is the point of creating a Frame object at all? I tried NOT
> doing it, like you said, and it seemed to work fine with my simple
> example. But is there a benefit to using a Frame object to group the
> widgets together? Or is it cleaner to just use the Tk object?

You will no doubt need to use frames to group widgets from time to
time. My previous point was simply: "don't use frames superfluously!".

Here is an example of creating a custom compound widget by sub-
classing frame (psst: this widget already exists in the Tix extension.

## START CODE ##
import Tkinter as tk
from Tkconstants import LEFT, YES, X, N

class LabelEntry(tk.Frame):
    def __init__(self, master, text='LE', **kw):
        tk.Frame.__init__(self, master, **kw)
        self.label = tk.Label(self, text=text, font=('Courier New',
12))
        self.label.pack(side=LEFT)
        self.entry = tk.Entry(self)
        self.entry.pack(side=LEFT, fill=X, expand=YES)

    def get(self):
        return self.entry.get()

    def set(self, arg):
        self.entry.delete(0, 'end')
        self.entry.set(arg)

if __name__ == '__main__':
    root = tk.Tk()
    for blah in ('   Name:', 'Address:', '  Phone:'):
        w = LabelEntry(root, text=blah)
        w.pack(fill=X, expand=YES, anchor=N, padx=5, pady=5)
    root.mainloop()
## END CODE ##

[toc] | [prev] | [standalone]


Page 2 of 2 — ← Prev page 1 [2]

Back to top | Article view | comp.lang.python


csiph-web