0

I want to change the color of the button when its pressed.

map = []

for y in range(20):
    for x in range(20):
        map.append(0)

def button_map():
    btn_c = ""
    if map[x+20*y] == 1:
        btn_c ="red"
    elif map[x+20*y] == 2:
        btn_c ="blue"
    elif map[x+20*y] == 0:
        btn_c ="orange"
    return btn_c

def button_map_set(x, y):
    if map[x+20*y] == 1:
        map[x+20*y] = 0
    elif map[x+20*y] == 0:
        map[x+20*y] = 1

main = Tk()
frame1 = Frame(main)
frame1.pack()
for y in range(20):
    for x in range(20):

I have tested this

        def test():
            button_map_set(x, y)

this

        test = button_map_set(x, y)

and this

        btn.bind("<btn>", button_map_set(x, y)

        btn = Button(framex, command = test, bg = button_map())
main.mainloop()

what happens: it executes when declared, but not when pressed

Zero
  • 73
  • 1
  • 6

1 Answers1

1

bind and command= expect "function name" - it means without () and arguments.

If you need to assign function with arguments then use lambda

Button(..., command=lambda:button_map_set(x, y))

or create function without arguments

def test():
    button_map_set(x, y)

Button(..., command=test)

if you need run more functions when you press button then use function

def test():
    button_map_set(x, y)
    button_map()

Button(..., command=test)

-

The same is with bind but bind sends event so function has to receive this information

def test(event):
    button_map_set(x, y)
    button_map()

btn.bind("<Button-1>", test)

<Button-1> means left mouse click.

-

If you need use the same functions with bind and command= you can use default value None for event

def test(event=None):
    button_map_set(x, y)
    button_map()

Button(..., command=test) # run `test(None)`
btn.bind("<Button-2>", test) # run `test(event)`

<Button-2> means right mouse click.


BTW: own button with 3 colors

import tkinter as tk

class MyButton(tk.Button):

    colors = ['red', 'blue', 'orange']

    def __init__(self, *args, **kwargs):
        tk.Button.__init__(self, *args, **kwargs)

        # current color number
        self.state = 0

        # set color
        self.config(bg=self.colors[self.state])

        # assign own function to click button 
        self.config(command=self.change_color)

    def change_color(self):
        # change current color number
        self.state = (self.state + 1) % len(self.colors)

        # set color
        self.config(bg=self.colors[self.state])



root = tk.Tk()

for __ in range(5):
    MyButton(root, text="Hello World").pack()

root.mainloop()

You can add more colors to the list colors and it will work too.

furas
  • 134,197
  • 12
  • 106
  • 148
  • I can see how it would fix the problem, but it made no difference. could it be that my problem lies elsewhere? – Zero Feb 03 '16 at 11:50
  • yes, if it doesn't work then you have different problem. – furas Feb 03 '16 at 11:52
  • use `print(x,y)` in this function to see what values you have. If you create buttons in `for` loop then all buttons may have the same value in `x`, `y`. – furas Feb 03 '16 at 12:02
  • btw: if you need only `0/1` then you could use `True/False` instead of `0/1` - and then you can change from `True` to `False` and from `False` to `True` in one line `variable = not variable` – furas Feb 03 '16 at 12:06
  • i use a variable to add a third option – Zero Feb 03 '16 at 12:08
  • I can create own Button (using original Button) with extra variables – furas Feb 03 '16 at 12:10
  • an issue found, all buttons are x,y = 19,19 – Zero Feb 03 '16 at 12:12
  • i know the issue, because all buttons are called btn all buttons have the same functions/position. is there a way to create multiple buttons the way i want it? – Zero Feb 03 '16 at 12:15
  • if you use `lambda` you can use `a=x,b=y` in `Button(..., command=lambda a=x, b=y: button_map_set(a,b))` – furas Feb 03 '16 at 12:15
  • see in answer example - own button with 3 colors – furas Feb 03 '16 at 12:23