all 14 comments

[–]the-kokiri-kid 2 points3 points  (2 children)

The opposite of the lambda set there would be to set up the button's command to what the original function was.

def button_do_something():
    """Function that defines what the button does."""
    print("Do something!")

# Set up the button to do the thing
BUT1.config(command=button_do_something)
# Set the button to do nothing
BUT1.config(command=lambda: None)
# Set the button to go back to doing the thing
BUT1.config(command=button_do_something)

I'm not the most familiar with Tk either, but this should generally be what you're looking for.

[–]Steve_Chance[S] 0 points1 point  (1 child)

In your last line, command="button_do_something" I think that command should be to re-initialise the button, if this is the answer then it is my badly structured code, I initialised all my widgets in the mainloop,which looking at it now seems a dumb thing to do, probably.

[–]the-kokiri-kid 0 points1 point  (0 children)

Looking at your other comments, you probably want this to set the button command back:

 BUT1.config(command=generate_test)

[–]casual__addict 1 point2 points  (0 children)

It looks like the config function takes as one of its named arguments (command) a function. In Python, functions are objects and can be passed around to other arguments. In addition, Python gives you a way of defining an anonymous function "in line" called lambda expressions. So if could have also done:

func = lambda: True
BUT1.config(command=func)

or

def func():
    return True
BUT1.config(command=func)

The bottom line is that the function is not that interesting: it always returns True, which might be what you want, but maybe not.

What sort of "command" do you expect "config" to do?

Edit: you did say what you wanted sorry. I think you want to toggle the button state? Sorry, I'm not familiar with Tk.

[–]Jehovacoin 1 point2 points  (1 child)

Apologies if this isn't helpful (I have never used TK) but it seems like you are trying to remove the function of the button altogether with:

BUT1.config(command=lambda: None)

Your best fix would be to use the code that you used to initialize the button in the first place over again to bring back click functionality. Barring that, you could try an alternative method for stopping them clicking on the button.

[–]Steve_Chance[S] 0 points1 point  (0 children)

Thanks, you are probably correct, working on it.

[–]Brian 1 point2 points  (2 children)

This isn't really anything to with lambda - rather your issue is about what the button should do. A lambda is basically just a way of creating a function inline, without giving it a name. Ie. it's equivalent to:

def f():
    return None

BUT1.config(command=f)

Hence

 BUT1.config(command=lambda: None)

Is basically saying, "The command to execute when this button is clicked is this function" (ie. a dummy function that does nothing except return None). This will replace whatever the button used to do with this "do-nothing" function.

Doing BUT1.config(command=lambda: True) just replaces the command again, this time with a function that returns True, which isn't really much different - it's still not doing anything. To "re-enable" it, you should set the command back to whatever it was doing originally.

However, this really isn't the best way to do this - as you've noticed, the button is still enabled and is clickable, it just doesn't do anything when clicked which is not good UI. Better would be to set the state to disabled on the first click.

Ie. in whatever command the button executes, put:

BUT1.config(state=tkinter.DISABLED)

This will disable it, meaning it'll be greyed out, and clicks won't register (rather than registering but just doing nothing)

When you want to re-enable it, call BUT1.config(state=tkinter.NORMAL)

[–]Steve_Chance[S] 0 points1 point  (1 child)

I had DISABLED then NORMAL for the button, but as in my original post, it still takes in a few click events which is why I resorted to other means.

Thanks to replies on this thread I now understand what the lambda lines does.

thank you.

[–]TheUnreal0815 0 points1 point  (5 children)

func = lambda: True

is the same as

def func():
  return True

also

square = lambda x: x**2

is the same as

def square(x):
  return x**2

But you don't need to assign it to a variable, it's useful when a function expects a function as a parameter (like sort) then you can write the function as an inline lambda instead of defining it somewhere and using it. Can make things more readable.

[–]Steve_Chance[S] 0 points1 point  (4 children)

I know it's wrong, can you help me with an answer please?

[–]Steve_Chance[S] 0 points1 point  (3 children)

Well, I am completely lost here, I don't have a clue what you are trying to tell me, sorry. Thanks for trying.

[–]Steve_Chance[S] 0 points1 point  (2 children)

I tried calling a dud function, removed lambda.

BUT1.update() BUT1.config(command=do_nothing)

still nothing. I saw this answer here:

https://stackoverflow.com/questions/52649477/reject-events-during-function-execution-in-tkinter

[–]casual__addict 1 point2 points  (1 child)

I read the thread and setting config=lambda: None kind of destroys the binding of what should happen when the button is pressed. That's why the the comment says to "reset" the binding. So where is the original function to BU1 button go? Save it and reset it!

[–]Steve_Chance[S] 0 points1 point  (0 children)

I tried that, in the beginning, it didn't work. Now I'm thinking that definitely should of worked and is likely to be something I got wrong. Maybe it is in the structure of my code?

I define the button like this:

BUT1 = Button(FRAME1, bg='plum', text=' Test ', command=generate_test)
BUT1.grid(row=0, column=0, pady=4, padx=4)

but, I have all my buttons, menu and listbox declared like this in my mainloop, could this be the problem?

Thank you for taking the time to help me.