Событие привязки Tkinter передается функции вместо переменной - PullRequest
1 голос
/ 07 июня 2019

Я пытаюсь сделать простую палитру цветов для приложения. Я генерирую массив меток с разными цветами фона. При нажатии на метку я хочу поместить шестнадцатеричный цвет в поле ввода в родительском виджете.

Все загружается правильно, но, похоже, я передаю экземпляр события bind моему методу set_color, а не шестнадцатеричному цвету. Что я делаю не так?

Я мог бы использовать кнопки с командами, но они загружались дольше.

# 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()

А вот небольшой пример, который запускает и воспроизводит поведение.

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 Ответ

1 голос
/ 07 июня 2019

Bind генерирует событие, которое вы должны использовать внутри лямбды:

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

В противном случае лямбда назначит событие hexcolor.

Обновление

Что касается проблем с ярлыками, которые не реагируют, я не смог воспроизвести это.Однако я немного подумал и придумал способ назначения ROW и COL, который кажется более питоническим:

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)

Остерегайтесь того, что я использую Python 3.6.5, и могут быть некоторые различия.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...