0

I acknowledge there is a similar question here: tkinter-creating-buttons-in-for-loop-passing-command-arguments

But that does not solve my problem.

from tkinter import *

Master = Tk()
Master.geometry("1920x1080")
Master.configure(bg = "#000000")

img1C1C1C = PhotoImage(file = f"#1C1C1C.png")
img505050 = PhotoImage(file = f"#505050.png")

def Enter(Widget, event):
  if not event.state:
    Widget.configure(image = img505050)

def Leave(Widget, event):
  if not event.state:
    Widget.configure(image = img1C1C1C)

for Row in range(5):
  for Column in range(10):
    x = 25 + 125 * Column + 25 * Column
    y = 25 + 100 * Row + 25 * Row
    
    Widget = Button(master = Master, bg = "#000000", image = img1C1C1C, bd = 0, borderwidth = 0, activebackground = "#000000", relief = "flat", highlightthickness = 0)
    Widget.bind("<Enter>", lambda event: Enter(Widget, event))
    Widget.bind("<Leave>", lambda event: Leave(Widget, event))
    Widget.place(x = x, y = y, width = 125, height = 100)

Here I am creating a simple script to create some rows of buttons and columns of buttons.

However when I hover over any button the image change only applied to the last button created by the loop. I have tried long and hard to fix this an I cannot I need some help thanks.

Looking on Google Coding in a different language like HTML, CSS and JS Looking on StackOverflow Looking on YouTube I have even tried BING

xdeltaxen
  • 11
  • 1
  • 1
    Are you aware that you don' t have to pass the widget? The `event` that is passed in has a reference to the widget (ie: `event.widget`). Also, it's not clear why you don't think that other question applies. The highest voted answer is exactly what you need to do if you want to pass the widget anyway. – Bryan Oakley Nov 03 '22 at 17:45
  • I tried doing lambda (str(Row) + str(Column)): ... and it did not work. I also tried adding the widgets to a matrix and that did not work – xdeltaxen Nov 03 '22 at 17:49
  • `lambda event, w=Widget: Enter(w, event)` would work. But as Bryan said, you don't need it. Look at [event parameter](https://stackoverflow.com/questions/68356340/what-is-the-use-of-the-event-parameter-argument-in-tkinter/73433401#73433401) and [lambda](https://stackoverflow.com/a/62742314/13629335) and may take a look at [event.state](https://stackoverflow.com/a/72917102/13629335) – Thingamabobs Nov 03 '22 at 17:50

1 Answers1

0

You do not need to pass Widget as part of the event handling. The callback is given an object that has a reference to the widget. You can write your callback and bindings like this:

def Enter(event):
  if not event.state:
    event.widget.configure(image = img505050)
...
Widget.bind("<Enter>", Enter)

If you really want to pass Widget to your existing callback even though the widget is part of the event object, you need to do what the question you pointed to recommends. It would look something like this:

Widget.bind("<Enter>", lambda event, widget=Widget: Enter(widget, event))
#                                  ^^^^^^^^^^^^^^^
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685