-3

I want my function to be executed after the button press. But as I run the program the button calls the function for all the buttons before I click on them. And when I press the button, after my output is showing, none of the buttons work.

Rest of the buttons in the programs are working fine in the same way.

#all the buttons calling the same function buttonEntry(num) with different parameters

button1 = Button(frame_bottom, text="1", width="20", height="6", bg=buttonColor, command=buttonEntry("1"))
button2 = Button(frame_bottom, text="2", width="20", height="6", bg=buttonColor, command=buttonEntry("2"))
button3 = Button(frame_bottom, text="3", width="20", height="6", bg=buttonColor, command=buttonEntry("3"))
button4 = Button(frame_bottom, text="4", width="20", height="6", bg=buttonColor, command=buttonEntry("4"))
button5 = Button(frame_bottom, text="5", width="20", height="6", bg=buttonColor, command=buttonEntry("5"))
button6 = Button(frame_bottom, text="6", width="20", height="6", bg=buttonColor, command=buttonEntry("6"))
button7 = Button(frame_bottom, text="7", width="20", height="6", bg=buttonColor, command=buttonEntry("7"))
button8 = Button(frame_bottom, text="8", width="20", height="6", bg=buttonColor, command=buttonEntry("8"))
button9 = Button(frame_bottom, text="9", width="20", height="6", bg=buttonColor, command=buttonEntry("9"))
button0 = Button(frame_bottom, text="0", width="20", height="6", bg=buttonColor, command=buttonEntry("0"))

#function which doesn't execute when button is pressed
def buttonEntry(num):
    n=num
    print(n)

I want 1 to be displayed when button1 is pressed, 2 to be displayed when button2 is pressed, so, on. But when I run the program, all the buttons run their commands at once and shows the output like:

1
2
3
4
5
6
7
8
9
0

Process finished with exit code 0

And the button pressed afterward doesn't display anything.

Dinesh Roy
  • 141
  • 4
  • 12

3 Answers3

0

Your aren't actually passing the function as the callback, you are passing the return value. To fix this, add lambda: before everything:

button1 = Button(frame_bottom, text="1", width="20", height="6", bg=buttonColor, command=lambda: buttonEntry("1"))
button2 = Button(frame_bottom, text="2", width="20", height="6", bg=buttonColor, command=lambda: buttonEntry("2"))

And so on.

iz_
  • 15,923
  • 3
  • 25
  • 40
0

The Button widget takes a callback function as its last argument, which would be called when the button is clicked. However, you are passing in buttonEntry("1"), which is None, since calling the buttonEntry function like that will set a local variable called n to be num and then prints num, but doesn't return anything, i.e. None.

If you want the function to be called when you click a button, you need to pass the function itself, not the result:

button1 = Button(frame_bottom, text="1", width="20", height="6", bg=buttonColor, command=buttonEntry)

Of course, that way, the callback won't know which button was called, as all of them would be calling buttonEntry(). So, instead of providing the function as a callback directly, you can make a lambda function that will get called, which then calls the buttonEntry function with the right value:

button1 = Button(frame_bottom, text="1", width="20", height="6", bg=buttonColor, command=lambda: buttonEntry("1"))

Read more about functions, return values and lambda if you want to understand more about why this works.

Grismar
  • 27,561
  • 4
  • 31
  • 54
0

The problem is with how you're setting the command for each button:

command=buttonEntry("1")

Because buttonEntry is a function, it is called at this point, which prints the number and assigns None to command.

command is also expecting a callable here. What you need to do is create a factory that creates functions that return the expected value, then update your Button setup:

def buttonEntryFactory(num):
    def buttonEntry():
        print num
    return buttonEntry

button1 = Button(frame_bottom, text="1", width="20", height="6", bg=buttonColor, command=buttonEntryFactory("1"))

Now, when you define the button, it creates a specific buttonEntry function for it with the correct value enclosed and assigns that function to command. When you click on the button, it will then call the function as expected.

In summary: command expects to be given a function (or callable) as an argument, so if you want to add custom parameters for commands, you'll need to use a factory to create a function with those parameters contained inside. (The other alternative is to use a lambda, but I find the factory approach a little cleaner).

Matthew Trevor
  • 14,354
  • 6
  • 37
  • 50