8000 bpo-42560: rewrite of Tkinter docs "life preserver" (GH-27842) · python/cpython@08830a4 · GitHub
[go: up one dir, main page]

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 08830a4

Browse files
rosemanambv
andauthored
bpo-42560: rewrite of Tkinter docs "life preserver" (GH-27842)
Co-authored-by: Łukasz Langa <lukasz@langa.pl>
1 parent 4d68917 commit 08830a4

File tree

2 files changed

+182
-145
lines changed

2 files changed

+182
-145
lines changed

Doc/library/tkinter.rst

Lines changed: 176 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -197,210 +197,241 @@ Additional modules:
197197
Tkinter Life Preserver
198198
----------------------
199199

200-
.. sectionauthor:: Matt Conway
201-
202-
203200
This section is not designed to be an exhaustive tutorial on either Tk or
204-
Tkinter. Rather, it is intended as a stop gap, providing some introductory
205-
orientation on the system.
201+
Tkinter. For that, refer to one of the external resources noted earlier.
202+
Instead, this section provides a very quick orientation to what a Tkinter
203+
application looks like, identifies foundational Tk concepts, and
204+
explains how the Tkinter wrapper is structured.
206205

207-
Credits:
206+
The remainder of this section will help you to identify the classes,
207+
methods, and options you'll need in your Tkinter application, and where to
208+
find more detailed documentation on them, including in the official Tcl/Tk
209+
reference manual.
208210

209-
* Tk was written by John Ousterhout while at Berkeley.
210211

211-
* Tkinter was written by Steen Lumholt and Guido van Rossum.
212+
A Hello World Program
213+
^^^^^^^^^^^^^^^^^^^^^
212214

213-
* This Life Preserver was written by Matt Conway at the University of Virginia.
215+
We'll start by walking through a "Hello World" application in Tkinter. This
216+
isn't the smallest one we could write, but has enough to illustrate some
217+
key concepts you'll need to know.
214218

215-
* The HTML rendering, and some liberal editing, was produced from a FrameMaker
216-
version by Ken Manheimer.
219+
::
217220

218-
* Fredrik Lundh elaborated and revised the class interface descriptions, to get
219-
them current with Tk 4.2.
221+
from tkinter import *
222+
from tkinter import ttk
223+
root = Tk()
224+
frm = ttk.Frame(root, padding=10)
225+
frm.grid()
226+
ttk.Label(frm, text="Hello World!").grid(column=0, row=0)
227+
ttk.Button(frm, text="Quit", command=root.destroy).grid(column=1, row=0)
228+
root.mainloop()
220229

221-
* Mike Clarkson converted the documentation to LaTeX, and compiled the User
222-
Interface chapter of the reference manual.
223230

231+
After the imports, the next line creates an instance of the :class:`Tk` class,
232+
which initializes Tk and creates its associated Tcl interpreter. It also
233+
creates a toplevel window, known as the root window, which serves as the main
234+
window of the application.
224235

225-
How To Use This Section
226-
^^^^^^^^^^^^^^^^^^^^^^^
236+
The following line creates a frame widget, which in this case will contain
237+
a label and a button we'll create next. The frame is fit inside the root
238+
window.
227239

228-
This section is designed in two parts: the first half (roughly) covers
229-
background material, while the second half can be taken to the keyboard as a
230-
handy reference.
240+
The next line creates a label widget holding a static text string. The
241+
:meth:`grid` method is used to specify the relative layout (position) of the
242+
label within its containing frame widget, similar to how tables in HTML work.
231243

232-
When trying to answer questions of the form "how do I do blah", it is often best
233-
to find out how to do "blah" in straight Tk, and then convert this back into the
234-
corresponding :mod:`tkinter` call. Python programmers can often guess at the
235-
correct Python command by looking at the Tk documentation. This means that in
236-
order to use Tkinter, you will have to know a little bit about Tk. This document
237-
can't fulfill that role, so the best we can do is point you to the best
238-
documentation that exists. Here are some hints:
244+
A button widget is then created, and placed to the right of the label. When
245+
pressed, it will call the :meth:`destroy` method of the root window.
239246

240-
* The authors strongly suggest getting a copy of the Tk man pages.
241-
Specifically, the man pages in the ``manN`` directory are most useful.
242-
The ``man3`` man pages describe the C interface to the Tk library and thus
243-
are not especially helpful for script writers.
247+
Finally, the :meth:`mainloop` method puts everything on the display, and
248+
responds to user input until the program terminates.
244249

245-
* Addison-Wesley publishes a book called Tcl and the Tk Toolkit by John
246-
Ousterhout (ISBN 0-201-63337-X) which is a good introduction to Tcl and Tk for
247-
the novice. The book is not exhaustive, and for many details it defers to the
248-
man pages.
249250

250-
* :file:`tkinter/__init__.py` is a last resort for most, but can be a good
251-
place to go when nothing else makes sense.
252251

252+
Important Tk Concepts
253+
^^^^^^^^^^^^^^^^^^^^^
253254

254-
A Simple Hello World Program
255-
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
255+
Even this simple program illustrates the following key Tk concepts:
256256

257-
::
257+
widgets
258+
A Tkinter user interface is made up of individual *widgets*. Each widget is
259+
represented as a Python object, instantiated from classes like
260+
:class:`ttk.Frame`, :class:`ttk.Label`, and :class:`ttk.Button`.
258261

259-
import tkinter as tk
262+
widget hierarchy
263+
Widgets are arranged in a *hierarchy*. The label and button were contained
264+
within a frame, which in turn was contained within the root window. When
265+
creating each *child* widget, its *parent* widget is passed as the first
266+
argument to the widget constructor.
260267

261-
class Application(tk.Frame):
262-
def __init__(self, master=None):
263-
super().__init__(master)
264-
self.master = master
265-
self.pack()
266-
self.create_widgets()
268+
configuration options
269+
Widgets have *configuration options*, which modify their appearance and
270+
behavior, such as the text to display in a label or button. Different
271+
classes of widgets will have different sets of options.
267272

268-
def create_widgets(self):
269-
self.hi_there = tk.Button(self)
270-
self.hi_there["text"] = "Hello World\n(click me)"
271-
self.hi_there["command"] = self.say_hi
272-
self.hi_there.pack(side="top")
273+
geometry management
274+
Widgets aren't automatically added to the user interface when they are
275+
created. A *geometry manager* like ``grid`` controls where in the
276+
user interface they are placed.
273277

274-
self.quit = tk.Button(self, text="QUIT", fg="red",
275-
command=self.master.destroy)
276-
self.quit.pack(side="bottom")
278+
event loop
279+
Tkinter reacts to user input, changes from your program, and even refreshes
280+
the display only when actively running an *event loop*. If your program
281+
isn't running the event loop, your user interface won't update.
277282

278-
def say_hi(self):
279-
print("hi there, everyone!")
280283

281-
root = tk.Tk()
282-
app = Application(master=root)
283-
app.mainloop()
284+
Understanding How Tkinter Wraps Tcl/Tk
285+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
284286

287+
When your application uses Tkinter's classes and methods, internally Tkinter
288+
is assembling strings representing Tcl/Tk commands, and executing those
289+
commands in the Tcl interpreter attached to your applicaton's :class:`Tk`
290+
instance.
285291

286-
A (Very) Quick Look at Tcl/Tk
287-
-----------------------------
292+
Whether it's trying to navigate reference documentation, trying to find
293+
the right method or option, adapting some existing code, or debugging your
294+
Tkinter application, there are times that it will be useful to understand
295+
what those underlying Tcl/Tk commands look like.
288296

289-
The class hierarchy looks complicated, but in actual practice, application
290-
programmers almost always refer to the classes at the very bottom of the
291-
hierarchy.
297+
To illustrate, here is the Tcl/Tk equivalent of the main part of the Tkinter
298+
script above.
292299

293-
Notes:
300+
::
294301

295-
* These classes are provided for the purposes of organizing certain functions
296-
under one namespace. They aren't meant to be instantiated independently.
302+
ttk::frame .frm -padding 10
303+
grid .frm
304+
grid [ttk::label .frm.lbl -text "Hello World!"] -column 0 -row 0
305+
grid [ttk::button .frm.btn -text "Quit" -command "destroy ."] -column 1 -row 0
297306

298-
* The :class:`Tk` class is meant to be instantiated only once in an application.
299-
Application programmers need not instantiate one explicitly, the system creates
300-
one whenever any of the other classes are instantiated.
301307

302-
* The :class:`Widget` class is not meant to be instantiated, it is meant only
303-
for subclassing to make "real" widgets (in C++, this is called an 'abstract
304-
class').
308+
Tcl's syntax is similar to many shell languages, where the first word is the
309+
command to be executed, with arguments to that command following it, separated
310+
by spaces. Without getting into too many details, notice the following:
305311

306-
To make use of this reference material, there will be times when you will need
307-
to know how to read short passages of Tk and how to identify the various parts
308-
of a Tk command. (See section :ref:`tkinter-basic-mapping` for the
309-
:mod:`tkinter` equivalents of what's below.)
312+
* The commands used to create widgets (like ``ttk::frame``) correspond to
313+
widget classes in Tkinter.
310314

311-
Tk scripts are Tcl programs. Like all Tcl programs, Tk scripts are just lists
312-
of tokens separated by spaces. A Tk widget is just its *class*, the *options*
313-
that help configure it, and the *actions* that make it do useful things.
315+
* Tcl widget options (like ``-text``) correspond to keyword arguments in
316+
Tkinter.
314317

315-
To make a widget in Tk, the command is always of the form::
318+
* Widgets are referred to by a *pathname* in Tcl (like ``.frm.btn``),
319+
whereas Tkinter doesn't use names but object references.
316320

317-
classCommand newPathname options
321+
* A widget's place in the widget hierarchy is encoded in its (hierarchical)
322+
pathname, which uses a ``.`` (dot) as a path separator. The pathname for
323+
the root window is just ``.`` (dot). In Tkinter, the hierarchy is defined
324+
not by pathname but by specifying the parent widget when creating each
325+
child widget.
318326

319-
*classCommand*
320-
denotes which kind of widget to make (a button, a label, a menu...)
327+
* Operations which are implemented as separate *commands* in Tcl (like
328+
``grid`` or ``destroy``) are represented as *methods* on Tkinter widget
329+
objects. As you'll see shortly, at other times Tcl uses what appear to be
330+
method calls on widget objects, which more closely mirror what would is
331+
used in Tkinter.
321332

322-
.. index:: single: . (dot); in Tkinter
323333

324-
*newPathname*
325-
is the new name for this widget. All names in Tk must be unique. To help
326-
enforce this, widgets in Tk are named with *pathnames*, just like files in a
327-
file system. The top level widget, the *root*, is called ``.`` (period) and
328-
children are delimited by more periods. For example,
329-
``.myApp.controlPanel.okButton`` might be the name of a widget.
334+
How do I...? What option does...?
335+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
330336

331-
*options*
332-
configure the widget's appearance and in some cases, its behavior. The options
333-
come in the form of a list of flags and values. Flags are preceded by a '-',
334-
like Unix shell command flags, and values are put in quotes if they are more
335-
than one word.
337+
If you're not sure how to do something in Tkinter, and you can't immediately
338+
find it in the tutorial or reference documentation you're using, there are a
339+
few strategies that can be helpful.
336340

337-
For example::
341+
First, remember that the details of how individual widgets work may vary
342+
across different versions of both Tkinter and Tcl/Tk. If you're searching
343+
documentation, make sure it corresponds to the Python and Tcl/Tk versions
344+
installed on your system.
338345

339-
button .fred -fg red -text "hi there"
340-
^ ^ \______________________/
341-
| | |
342-
class new options
343-
command widget (-opt val -opt val ...)
346+
When searching for how to use an API, it helps to know the exact name of the
347+
class, option, or method that you're using. Introspection, either in an
348+
interactive Python shell or with :func:`print`, can help you identify what
349+
you need.
344350

345-
Once created, the pathname to the widget becomes a new command. This new
346-
*widget command* is the programmer's handle for getting the new widget to
347-
perform some *action*. In C, you'd express this as someAction(fred,
348-
someOptions), in C++, you would express this as fred.someAction(someOptions),
349-
and in Tk, you say::
351+
To find out what configuration options are available on any widget, call its
352+
:meth:`configure` method, which returns a dictionary containing a variety of
353+
information about each object, including its default and current values. Use
354+
:meth:`keys` to get just the names of each option.
350355

351-
.fred someAction someOptions
356+
::
352357

353-
Note that the object name, ``.fred``, starts with a dot.
358+
btn = ttk.Button(frm, ...)
359+
print(btn.configure().keys())
354360

355-
As you'd expect, the legal values for *someAction* will depend on the widget's
356-
class: ``.fred disable`` works if fred is a button (fred gets greyed out), but
357-
does not work if fred is a label (disabling of labels is not supported in Tk).
361+
As most widgets have many configuration options in common, it can be useful
362+
to find out which are specific to a particular widget class. Comparing the
363+
list of options to that of a simpler widget, like a frame, is one way to
364+
do that.
358365

359-
The legal values of *someOptions* is action dependent. Some actions, like
360-
``disable``, require no arguments, others, like a text-entry box's ``delete``
361-
command, would need arguments to specify what range of text to delete.
366+
::
362367

368+
print(set(btn.configure().keys()) - set(frm.configure().keys()))
363369

364-
.. _tkinter-basic-mapping:
370+
Similarly, you can find the available methods for a widget object using the
371+
standard :func:`dir` function. If you try it, you'll see there are over 200
372+
common widget methods, so again identifying those specific to a widget class
373+
is helpful.
365374

366-
Mapping Basic Tk into Tkinter
367-
-----------------------------
375+
::
368376

369-
Class commands in Tk correspond to class constructors in Tkinter. ::
377+
print(dir(btn))
378+
print(set(dir(btn)) - set(dir(frm)))
370379

371-
button .fred =====> fred = Button()
372380

373-
The master of an object is implicit in the new name given to it at creation
374-
time. In Tkinter, masters are specified explicitly. ::
381+
Navigating the Tcl/Tk Reference Manual
382+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
375383

376-
button .panel.fred =====> fred = Button(panel)
384+
As noted, the official `Tk commands <https://www.tcl.tk/man/tcl8.6/TkCmd/contents.htm>`_
385+
reference manual (man pages) is often the most accurate description of what
386+
specific operations on widgets do. Even when you know the name of the option
387+
or method that you need, you may still have a few places to look.
377388

378-
The configuration options in Tk are given in lists of hyphened tags followed by
379-
values. In Tkinter, options are specified as keyword-arguments in the instance
380-
constructor, and keyword-args for configure calls or as instance indices, in
381-
dictionary style, for established instances. See section
382-
:ref:`tkinter-setting-options` on setting options. ::
389+
While all operations in Tkinter are implemented as method calls on widget
390+
objects, you've seen that many Tcl/Tk operations appear as commands that
391+
take a widget pathname as its first parameter, followed by optional
392+
parameters, e.g.
383393

384-
button .fred -fg red =====> fred = Button(panel, fg="red")
385-
.fred configure -fg red =====> fred["fg"] = red
386-
OR ==> fred.config(fg="red")
394+
::
387395

388-
In Tk, to perform an action on a widget, use the widget name as a command, and
389-
follow it with an action name, possibly with arguments (options). In Tkinter,
390-
you call methods on the class instance to invoke actions on the widget. The
391-
actions (methods) that a given widget can perform are listed in
392-
:file:`tkinter/__init__.py`. ::
396+
destroy .
397+
grid .frm.btn -column 0 -row 0
393398

394-
.fred invoke =====> fred.invoke()
399+
Others, however, look more like methods called on a widget object (in fact,
400+
when you create a widget in Tcl/Tk, it creates a Tcl command with the name
401+
of the widget pathname, with the first parameter to that command being the
402+
name of a method to call).
395403

396-
To give a widget to the packer (geometry manager), you call pack with optional
397-
arguments. In Tkinter, the Pack class holds all this functionality, and the
398-
various forms of the pack command are implemented as methods. All widgets in
399-
:mod:`tkinter` are subclassed from the Packer, and so inherit all the packing
400-
methods. See the :mod:`tkinter.tix` module documentation for additional
401-
information on the Form geometry manager. ::
404+
::
402405

403-
pack .fred -side left =====> fred.pack(side="left")
406+
.frm.btn invoke
407+
.frm.lbl configure -text "Goodbye"
408+
409+
410+
In the official Tcl/Tk reference documentation, you'll find most operations
411+
that look like method calls on the man page for a specific widget (e.g.,
412+
you'll find the :meth:`invoke` method on the
413+
`ttk::button <https://www.tcl.tk/man/tcl8.6/TkCmd/ttk_button.htm>`_
414+
man page), while functions that take a widget as a parameter often have
415+
their own man page (e.g.,
416+
`grid <https://www.tcl.tk/man/tcl8.6/TkCmd/grid.htm>`_).
417+
418+
You'll find many common options and methods in the
419+
`options <https://www.tcl.tk/man/tcl8.6/TkCmd/options.htm>`_ or
420+
`ttk::widget <https://www.tcl.tk/man/tcl8.6/TkCmd/ttk_widget.htm>`_ man
421+
pages, while others are found in the man page for a specific widget class.
422+
423+
You'll also find that many Tkinter methods have compound names, e.g.,
424+
:func:`winfo_x`, :func:`winfo_height`, :func:`winfo_viewable`. You'd find
425+
documentation for all of these in the
426+
`winfo <https://www.tcl.tk/man/tcl8.6/TkCmd/winfo.htm>`_ man page.
427+
428+
.. note::
429+
Somewhat confusingly, there are also methods on all Tkinter widgets
430+
that don't actually operate on the widget, but operate at a global
431+
scope, independent of any widget. Examples are methods for accessing
432+
the clipboard or the system bell. (They happen to be implemented as
433+
methods in the base :class:`Widget` class that all Tkinter widgets
434+
inherit from).
404435

405436

406437
How Tk and Tkinter are Related

Doc/tools/susp-ignored.csv

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,12 @@ library/tarfile,,:xz,'r:xz'
233233
library/tarfile,,:xz,'w:xz'
234234
library/time,,:mm,
235235
library/time,,:ss,
236+
library/tkinter,294,::,ttk::frame .frm -padding 10
237+
library/tkinter,294,::,"grid [ttk::label .frm.lbl -text ""Hello World!""] -column 0 -row 0"
238+
library/tkinter,294,::,"grid [ttk::button .frm.btn -text ""Quit"" -command ""destroy .""] -column 1 -row 0"
239+
library/tkinter,304,::,ttk::frame
240+
library/tkinter,402,::,ttk::button
241+
library/tkinter,410,::,ttk::widget
236242
library/tracemalloc,,:limit,"for index, stat in enumerate(top_stats[:limit], 1):"
237243
library/turtle,,::,Example::
238244
library/unittest,,:foo,"self.assertEqual(cm.output, ['INFO:foo:first message',"

0 commit comments

Comments
 (0)
0