1

I am trying to make a simple color picker for an application. I am generating an array of labels with different background colors. When the label is clicked, I want to put the hex color into an entry field in the parent widget.

Everything loads correctly, but it seems I am passing the bind event instance to my set_color method, and not actually the hex color. What am I doing wrong?

I could use buttons with commands, but those take longer to load.

# Python 2.7
import Tkinter as tk
from tkFont import Font
import math

class ColorPicker(tk.Toplevel):
    def __init__(self, parent):
        tk.Toplevel.__init__(self, parent)
        self.parent = parent
        self.title("ColorPicker")

        self.frame = tk.Frame(self)
        self.frame.pack()

        self.buttonfont = Font(family="Arial", size=5)

        ROW, COL = 0, 0
        COLORS = xrange(1, int("FFFFFF", base=16), 50000)
        for color in COLORS:
            hexcolor = "#" + str(hex(color))[2:]
            hexcolor += "0"*(7 - len(hexcolor))

            l = tk.Label(self.frame, bg=hexcolor, text=hexcolor, font=self.buttonfont)
            l.bind("<Button-1>", lambda x=hexcolor: self.set_color(x))
            l.grid(row=ROW, column=COL)

            ROW += 1
            if ROW > math.sqrt(len(COLORS)):
                ROW = 0
                COL += 1

    def set_color(self, color):
        self.parent.entry_background_color.delete(0, tk.END)
        self.parent.entry_background_color.insert(0, color)
        self.destroy()

And here is a small example that runs and reproduces the behavior.

import Tkinter as tk

def p(s, *args):
    print(s)

app = tk.Tk()
frame = tk.Frame(app)
frame.pack()

for i in range(3):
    label = tk.Label(app, text="Press Me")
    label.pack()
    label.bind("<Button-1>", lambda i=i: p("Hello World {} times".format(i)))

app.mainloop()

1 Answer 1

1

Bind is generating an event which you must consume within the lambda:

l.bind("<Button-1>", lambda event, x=hexcolor: self.set_color(x))
#                             ^         ^
#         consume event-------|         | and then assign x

Otherwise lambda will assign the event to hexcolor.

Update

As for the problems with labels not being responsive, I have not been able to reproduce that. I did however give it some thought and came up with a way of assigning ROW and COL which feels more pythonic:

import Tkinter as tk
import math

class ColorPicker(tk.Toplevel):
    def __init__(self, parent):
        tk.Toplevel.__init__(self, parent)
        self.parent = parent
        self.title("ColorPicker")

        self.frame = tk.Frame(self)
        self.frame.pack()

        ROW, COL = 0, 0
        COLORS = xrange(1, int("FFFFFF", base=16), 50000)
        for count, color in enumerate(COLORS):
            hexcolor = "#" + str(hex(color))[2:]
            hexcolor += "0"*(7 - len(hexcolor))

            ROW = count // int(math.sqrt(len(COLORS)))
            COL = count % int(math.sqrt(len(COLORS)))

            l = tk.Label(self.frame, bg=hexcolor, text=hexcolor)
            l.bind("<Button-1>", lambda event, x=hexcolor: self.set_color(x))
            l.grid(row=ROW, column=COL)

    def set_color(self, color):
        print color

root = tk.Tk()
app = ColorPicker(root)

Beware that I'm running Python 3.6.5 and there may be some differences.

Sign up to request clarification or add additional context in comments.

3 Comments

Awesome. But for some reason the top two rows in my label array are inactive. And when I click on a label, it actually picks the color from the label two rows up. That is weird. Do you see an obvious reason for why that might happen?
Aaahh..., sorry; I'm on my way out for some beers. So I wont have a look until tomorrow. Try starting a new question about it and perhaps someone else may have an answer.
I approve of your plans.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.