How to capture parameters of the object that called an event in Tkinter?

Asked

Viewed 485 times

1

I have 3 buttons, two with the same name and one with different name and each with its properties, I would like to know how to capture the text of each button in the same definition. Of course, I want to capture the property of the button that called the event.

For example, in my graphical interface, these three buttons appear:

Facts
rumours
Overcoming?

When I click the button "Facts", i want to capture the Text parameter of this button, i.e., the Facts. If I click on "rumours" sharing the same button name "Facts", I want to capture the rumors. There’s a way I can do this with Tkinter?

My code:

try:
    from tkinter import *
except:
    from Tkinter import *

tela = Tk()

def clicar():
   # Como exibir o texto do botão clicado?
   print(btn["text"])

btn = Button(tela,text="Fatos",font=("",20),bg="black",fg="white",command=clicar)
btn.grid(row=1,column=1)

btn = Button(tela,text="boatos",font=("",20),bg="black",fg="white",command=clicar)
btn.grid(row=2,column=1)

btn2 = Button(tela,text="Supertição?",font=("",20),bg="black",fg="white",command=clicar)
btn2.grid(row=3,column=1)

tela.mainloop()

Color palette with the jsbueno, Thank you very much!:

try:
    from tkinter import *
except:
    from Tkinter import *

# Instância
tela = Tk()

# Lista de cores que vão aparecer na paleta
cores = ["#1bbc9b","#2ecd71","#3598db","#9b58b5","#5c6d7d","#16a086","#27ae61","#2a80b9","#8f44ad","#2d3e50","#f1c40f","#e77e23","#e84c3d","#ecf0f1","#95a5a5","#f39c11","#d55401","#c1392b","#bec3c7","#7e8c8d"]

# Definição que vai apenas exibir a cor escolhida.
def clicar(btn):
   print(btn["bg"])

linha = 1
# Variável que vai andar pela lista
quantidade = 0
while linha <=4:
    coluna = 1
    while coluna<=4:
        # Atualiza dados da cor
        cor_analise = cores[quantidade]

        # Cria um botão
        btn = Button(tela,font=(" ",12),bg=cor_analise,fg="white",activebackground=cor_analise,highlightbackground="white",highlightthickness=1,height=1,width=3)
        btn["command"] = lambda btn=btn: clicar(btn)
        btn.grid(row=linha,column=coluna)

        # Atualiza os andantes 
        coluna=coluna+1
        quantidade = quantidade+1
    linha = linha+1

tela.mainloop()
  • Why you need to create the first two buttons with the same variable btn? Can’t you create a variable for each button? The way you are doing the variable that creates the "Facts" button is overwritten when you create the "hearsay" button" .

  • I wanted to optimize the creation of a color table with approximately 200 colors, there are more than 400 lines for this and thousands of parameters to pass(If I remember some detail, I have to change in the 200 lines.) Using loops with x and y I create the whole "table" with 30 lines. In this case, each "button" assigns its color and its text according to a list of all 200 colors. And in the program that I’m doing, it’s going to happen basante this. If I can capture the parameter from a specific button, my code will be reduced by more than 95%.

  • I updated my question using a beta version of the palette, runs it there in Python3, the optimization is fantastic.

  • This code is poorly done ok, it was just a test even, the official version of the palette is still in alpha and the code has been optimized at least 3 times more than the one above.

1 answer

1


A Tkinter "command" response call does not carry any information of what was clicked - the function is called without any parameter, and therefore has no information about how or why it was called.

The only way to have different actions for each function is to actually have different functions for each control.

The good news is that this different function does not need to be declared in the program, with def, and lines of code: it can be any calling object, which adds information about the button or control where the event happened, and then calls a main function, but passing parameters to more.

One way to create these distinct functions for each button is by using the keyword lambda, that allows you to create functions as part of an expression (and so you don’t need 3 or 4 more lines for each button).

Another detail if you want the function that will treat the event to receive the button itself as parameter, the helper function cannot be created along with that button: it needs the reference to the object, so it has to be assigned after it already exists.

The code goes something like this:

def clicar(btn):
   # Como exibir o texto do botão clicado?
   print(btn["text"])

btn = Button(tela,text="Fatos",font=("",20),bg="black",fg="white")
btn["command"] = lambda btn=btn: clicar(btn)
btn.grid(row=1,column=1)

btn = Button(tela,text="boatos",font=("",20),bg="black",fg="white",command=clicar)
btn["command"] = lambda btn=btn: clicar(btn)
btn.grid(row=2,column=1)

There’s only one more trick used there - is that when creating the functions lambda with the default parameter, the value that variable btn has at the moment where the lambda is created (i.e., when the line is executed), it is stored as part of the lambda itself. This is very important - because if the lambda function simply used the variable btn that there is "on the outside", in the code that is creating the buttons, the content of btn used would be from the moment the button was clicked: that is, no matter which button was clicked, the last button created would be passed as parameter.

As for re-using variable names to create multiple controls, whether in a loop or in explicit creation - this is in fact no problem at all, and is a common practice in code that creates graphical interfaces.

On the other hand, a Code to pay attention is the identation of the code: try to use a fixed identation of 4 spaces in each block - you will see that the code is much more readable and less messy. Using a variable indentation, based on the line that opens the block is not a syntax error, but is not the recommendation of none Python style guide, and makes the code unpleasant for conference and reading - including for those who will answer questions about it.

  • Man, solved my problem perfectly, thank you very much! I will incorporate the new version of my color palette in the question. Ball show!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.