Tcl Error

11 May, 2017

丁明 writes (edited for spelling):

In your book <<python for kids>> chapter 13, when I run the program, the python shell has a error I can't understand. my python version 3.6.0. Thank you for your reply!!

error.png

I'm not sure if the Chinese edition has captured the text on page 199 of the English version of the book:

You may see error messages written to the shell when you close the game window. This is because when you close the window, the code is breaking out of the while loop, and Python is complaining about it.

The is exactly the error you are seeing when you run that code and then close the window. You are stopping (interrupting) Python while it is running the code, and an error message is displayed as a consequence.

Basically, you can ignore the message, but if you want to know how to get rid of it for good, one option is to replace the loop at the bottom:

while True:
    ball.draw()
    tk.update_idletasks()
    tk.update()
    time.sleep(0.01)

...with this...

try:
    while True:
        ball.draw()
        tk.update_idletasks()
        tk.update()
        time.sleep(0.01)
except TclError:
    pass

You can find more about error handling here: https://wiki.python.org/moin/HandlingExceptions


askcolor

18 Jan, 2017

Isai writes:

I am having trouble with this code in page 176:

from tkinter import *
colorchooser.askcolor()

When I load it into IDLE, I get a blank canvas, and I can't close it, I have to restart the shell.

I have installed the proper ActiveTcl version (8.5), and no longer get the message giving me errors on startup.

When I run the previous code I was playing with (page 174), the canvas pops up and it all works again. Weirdly enough, the color picker pops up unprompted! I noticed that it does not bring up any buttons that appear in your book: [OK] [Cancel].

That's a bit of a gap in the book, because it doesn't make it clear that you need to create an instance of the top-level Tk widget first, before running that particular example (using tk = Tk()). So the first time you run this function: colorchooser.askcolor(), it's hanging, waiting for something that isn't there yet. Then you run the code on the previous page (which does create the Tk object), and that's when you suddenly get a popup dialog with the colorchooser in it.

So the code should really look like this:

from tkinter import *
from tkinter import colorchooser
tk = Tk()
tk.update()
colorchooser.askcolor()

When you run that, you should then get the colorchooser dialog immediately.

Update #1: One step I missed, is a call to tk.update(), which forces tk to update the screen. Once that's executed, the chooser will appear. The example is updated above.

Update #2: On Windows you need to explicitly import colorchooser for the code to work properly (example updated again).


Text position in tkinter

08 Dec, 2016

Drew M writes:

I have a question I am sure I don't know :) In tkinter I am creating a game and can't figure out how to set dimensions for text. I need it on the middle. My canvas is 1000 by 1000 so I divided in half. Which is of course 500. Now again, my question is how to put it there.

Adding text to a canvas is straightforward (similar to adding any other item, such as a line, or a rectangle). You say "middle" and not "center", so I assume you don't want the text directly in the center of the canvas? I've defined a smaller canvas here, but the principle is the same:

from tkinter import *
tk = Tk()
canvas = Canvas(tk, width=100, height=100, bd=0, highlightthickness=0)
canvas.create_text(50, 50, text='text')
canvas.pack()
tk.update()

text position center

So if you don't want the center, I'm guessing your problem is that this code...

from tkinter import *
tk = Tk()
canvas = Canvas(tk, width=100, height=100, bd=0, highlightthickness=0)
canvas.create_text(50, 0, text='text')
canvas.pack()
tk.update()

...(with coordinates of 50, 0) results in partially obscured text:

text position middle

The answer, is to use the named parameter anchor in the create_text function:

canvas.create_text(50, 0, text='text', anchor=N)

The anchor parameter controls the positioning of an item in terms of its coordinates. The default value is CENTER (so using this puts the center of the text at the coordinates (50, 0) in the earlier example), but you can also use NW, N, NE (effectively top-left, top-middle, top-right), W, E (left and right), and SW, S, SE (bottom-left, bottom-middle, bottom-right). So N puts the top and middle point of the text at the coordinates (50, 0), like so:

text position N

I hope that helps.


A parameter called evt

26 Jan, 2016

Dudley B writes:

I'm a Business Analyst trying to learn how to code. Luckily there's Python, a suitable language for absolute beginners like me. Thank God also for your book, Python for Kids. It's a great book which explains Python fundamentals in a fun and easy way. In Chapter 14 of the book, page 208, there is a parameter called "evt":

def turn_left(self, evt):
    self.x = -2
def turn_right(self, evt):
    self.x = 2

I can't figure out what this parameter is for, and why it's there since there is no value passed on to it. Please help me understand why "evt" is needed for those functions.

The evt parameter isn't brilliantly explained in that chapter, now that I look back at it. If you go back to the section titled "Making an object React to something" in Chapter 12, there's a description there of event bindings. The function described takes a parameter called event. After you've "told" tkinter about the function (that's the binding part), when an event occurs (such as the mouse being moved, or keyboard being pressed) it calls that function with an object containing more information (such as what sort of event it was).

The parameter evt on page 208, is simply a shortened name for the parameter event mentioned in the earlier chapter. In fact, the name isn't important at all -- you could even call it bob, or aardvark, or anything else you like.

By the way, another way of thinking about the tkinter event binding is that it's like a contract between two people. Let's say between a surfer, and an old man living on a cliff above the sea. The surfer says to the old man, "send me a message and let me know how high the surf is, whenever it changes". The function is that contract, and the message about the surf is the parameter value.

Hopefully that helps.


Tkinter mainloop issue on Raspberry Pi

26 Aug, 2015

Martin writes:

First of all thank you for writing "Python for Kids". It's a great book and offers "instant gratification". My 8-year-old is already hacking his way through the pages on his brand new Raspberry Pi.

He (we) ran into a bit of trouble when we started playing with Tkinter.

Your initial examples don't ever call mainloop() or update(). Turns out, on the Raspi, in IDLE, those examples don't work as expected - nothing appears on screen. Until you run mainloop() that is. raspberry pi screenshot

If you run a pure python3 interpreter inside a shell window, your examples work. [They will also not work on Windows inside a Python 2.7.10 IDLE.]

Could you throw any light on why things work without calling mainloop() on some setups but not on others?

Turns out that trying to reproduce your problem - without having a RPi to hand - was a lot more difficult than I expected. Even after getting Raspbian going with QEMU, I couldn't get a menu to display so that I could run IDLE (solution: create an empty file, and from the file's context menu you can then access the Terminal). However, when I ran IDLE, it only worked in "no subprocess mode" (see the first chapter of the book). If I run without specifying -n, I get the following error:

qemu error (small image)

Only after going through the above, did I remember that there was an issue with IDLE & tkinter on Python 3.2 (when running without -n). And sure enough, when running with 3.2 on my PC, I get the exact same problem (it doesn't occur with later versions of Python).

Best thing you can do, is to run IDLE with the -n flag - the turtle/tkinter code you run will be more stable as a consequence (and there's no need to call mainloop).

(PS. as for Python 2.7.x, many of the code samples won't work - the book is only intended to be used with Python 3.x)


Restart when running tkinter

13 Jun, 2014

Craig S writes:

My son is having a problem running the random rectangle program on page 174 of Python for Kids. He is using version 2.7.7, so the Tkinter module must be capitalized (just so you don't suggest to capitalize it). Every time he tries to run the module, it comes up with a new window saying, "RESTART". He tried to copy and paste your code, but came up with the same results. This is the code he's written.
from Tkinter import *
import random
tk = Tk()
canvas = Canvas(tk, width=400,height=400)
def random_rectangle(width, height):
    ...
random_rectangle(400, 400)

This is what comes up when he runs it.
Python 2.7.7 (default, Jun 1 2014, 14:17:13) on win32
Type "copyright", "credits" or "license()" for more information.
>>> =============== RESTART ===============

Please share some advice. Thanks.

A couple of thoughts:

  1. He's missing the pack function after the 4th line of that code (canvas.pack())
  2. You're probably not running Idle in "No Subprocess" mode (see Chapter 1 of the book for setup instructions). If that doesn't work for you, for some reason, then best thing to do is use a text editor, save the code and then run it from the command prompt by typing python yourscript.py (see http://windows.microsoft.com/en-us/windows/command-prompt-faq for instructions on running the command prompt if you're not aware how to do that)
  3. You may hit other weird issues if you're not using Python3, since all the code in the book was written and tested with 3.x. Much of it is probably fine, but no guarantees there...

Python on the iPad?

10 Mar, 2014

Beth S writes:

I teach gifted elementary-aged students in Albuquerque, NM. A few of my students and I have been working through your book. We have limited desktops in our classroom, but we also have access to several iPads. In researching the various apps available, I’ve realized that most (if not all?) do not include the _tkinter module. To be honest, I’m rather new to programming myself!

Do you have a recommendation for an iPad app that would be appropriate for students using your book?

Thank you for your time and your ability to clearly explain the basics of Python!

I'm afraid I don't know of any way to use an iPad for Python, other than by jail-breaking the device (and even then I have no idea whether tkinter would work anyway - I think unlikely).

The only thought I had was whether you could use the desktop PCs in your class to run multiple VMs (using something like VirtualBox) and then connect to those using a Remote Desktop App for the iPad. Not straightforward to set up, but it might accomplish what you want (assuming the desktops are reasonably powerful of course).

Sorry I can't be much help there.

Update: since sending my initial reply, I came across this discussion, which explains why you're not likely to see tkinter on the iPad anytime soon.


Tkinter problems on the Raspberry Pi

09 Jul, 2013

Ben writes:

I am 12 and I am reading your book, Python for Kids. I have recently confronted a problem with the module tkinter. I have recently got a rasberry pi to program on python. I am pretty sure that tkinter is already installed on python, but when I run something like:

def hello():
    print('hello there')
from tkinter import *
tk = Tk()
btn = Button(tk, text='click me', command=hello)
btn.pack()

There is nothing that pops up! I am frustrated and need help! Please help, me and my father are new to linux by the way and don't know what to do.

Ben is using Debian Linux on his Raspberry Pi. After a bit of to-ing and fro-ing, we eventually found that tkinter was definitely installed, but it looks like (according to this stackoverflow question that his father found) the tkinter window doesn't appear unless you use: tk.mainloop().

So if you're trying the code on page 178 (for example) on a Pi, you might need to add one line to get it to work successfully:

###
>>> from tkinter import *
>>> tk = Tk()
>>> canvas = Canvas(tk, width=400, height=400)
>>> canvas.pack()
>>> canvas.create_arc(10, 10, 200, 80, extent=45, style=ARC)
>>> canvas.create_arc(10, 80, 200, 160, extent=90, style=ARC)
>>> canvas.create_arc(10, 160, 200, 240, extent=135, style=ARC)
>>> canvas.create_arc(10, 240, 200, 320, extent=180, style=ARC)
>>> canvas.create_arc(10, 320, 200, 400, extent=359, style=ARC)###
>>> tk.mainloop()