pythontkinterturtle-graphicspython-turtle

How to avoid bad color string error in Python turtle with Tkinter Text input?


I'm working on a project to control turtle from tkinter, but when I try to change the colour (to red) the code shows such an error:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\acer\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 1892, in __call__
    return self.func(*args)
  File "C:\Users\acer\PycharmProjects\Lesson1\1.py", line 81, in <lambda>
    colourer = Button(text='Colour:', width=15, height=3, command=lambda: colour_change(colour, pen))
  File "C:\Users\acer\PycharmProjects\Lesson1\1.py", line 49, in colour_change
    feather.color(new_color)
  File "C:\Users\acer\AppData\Local\Programs\Python\Python39\lib\turtle.py", line 2217, in color
    pcolor = self._colorstr(pcolor)
  File "C:\Users\acer\AppData\Local\Programs\Python\Python39\lib\turtle.py", line 2697, in _colorstr
    return self.screen._colorstr(args)
  File "C:\Users\acer\AppData\Local\Programs\Python\Python39\lib\turtle.py", line 1159, in _colorstr
    raise TurtleGraphicsError("bad color string: %s" % str(color))
turtle.TurtleGraphicsError: bad color string: red

Here's the code (first you write the colour, then save the change and click on the 'Colour'):

import turtle
from tkinter import *

# Windows created
control = Tk()
pen = turtle.Turtle()
# A bit of design
# Button size: 15 = 115 px, 1 = 7 and 2/3 px
pen.shape('turtle')
control.title('Turtle controller v1.0')
control.geometry('345x168')
colour = ""


def colour_change(new_color, feather, hexa=False, rgb=False):
    if hexa is True:
        feather.color('#%s' % new_color)
    elif rgb is True:
        feather.colormode(255)
        feather.color(new_color)
    else:
        feather.color(new_color)


def changecolour():
    global colour
    colour = colourin.get(1.0, END)


colourer = Button(text='Colour', width=15, height=3, command=lambda: colour_change(colour, pen))
colourer.place(x=0, y=112)
colourin = Text(width=15, height=3)
colourin.place(x=115, y=112)
colourconv = Button(text='Save change', width=15, height=3, command=changecolour)
colourconv.place(x=230, y=112)
# Window mainloop
turtle.mainloop()
control.mainloop()

I tried to input Red, red and "red", none of which worked. I tried to debug myself - the transfer from Tkinter works perfectly, but the turtle does not accept the string.


Solution

  • The problem is subtle. To debug this, examine the string with repr():

    colour = colourin.get(1.0, END)
    print(repr(colour))
    

    You'll see this prints:

    'red\n'
    

    Now the problem is clear: there's a trailing newline. Strip it:

    colour = colourin.get(1.0, END).strip()
    

    It's been pointed out in the comments that you can improve your Tkinter code a bit as well. 1.0 isn't a proper text index--prefer "1.0".

    "end-1c" instead of END will skip the last character, but I'd still .strip() anyway, since the user may have added arbitrary whitespace. Other validation and cleaning is likely necessary, depending on how you want to handle bad input.