Suponha que eu tenha Button
feito o seguinte com o Tkinter em Python:
import Tkinter as Tk
win = Tk.Toplevel()
frame = Tk.Frame(master=win).grid(row=1, column=1)
button = Tk.Button(master=frame, text='press', command=action)
O método action
é chamado quando pressiono o botão, mas e se eu quisesse passar alguns argumentos para o método action
?
Eu tentei com o seguinte código:
button = Tk.Button(master=frame, text='press', command=action(someNumber))
Isso apenas invoca o método imediatamente e pressionar o botão não faz nada.
Respostas:
Pessoalmente, prefiro usá
lambdas
-lo nesse cenário, porque é mais claro e simples e também não força você a escrever muitos métodos de invólucro, se você não tiver controle sobre o método chamado, mas isso certamente é uma questão de gosto.É assim que você faria com um lambda (observe também que há alguma implementação de currying no módulo funcional, para que você possa usá-lo também):
fonte
partial
funciona neste caso."This just invokes the method immediately, and pressing the button does nothing"
acontece?callback=lambda x=x: f(x)
como emfs = [lambda x=x: x*2 for x in range(5)] ; print [f() for f in fs]
Isso também pode ser feito usando
partial
as funções da biblioteca padrão , desta forma:fonte
button = Tk.Button(master=frame, text='press', command=partial(action, arg))
action_with_args = partial(action, arg1, arg2... argN)
GUI de exemplo:
Digamos que eu tenho a GUI:
O que acontece quando um botão é pressionado
Veja que quando
btn
pressionado, ele chama sua própria função, que é muito semelhante aobutton_press_handle
exemplo a seguir:com:
Você pode simplesmente pensar que
command
opção deve ser definida como, a referência ao método que queremos ser chamado, semelhante acallback
inbutton_press_handle
.Chamando um método ( retorno de ) quando o botão é pressionado
Sem argumentos
Então, se eu quisesse
print
algo quando o botão for pressionado, seria necessário definir:Preste muita atenção para a falta de
()
com oprint
método que é omitido no sentido de que: "Este é o nome do método que eu quero que você chame quando pressionado , mas . Não chamá-lo apenas neste instante"No entanto, eu não passei nenhum argumento paraprint
que ele imprimisse o que imprimir quando chamado sem argumentos.Com argumento (s)
Agora, se eu também quisesse passar argumentos para o método que gostaria de ser chamado quando o botão for pressionado, poderia usar as funções anônimas, que podem ser criadas com a instrução lambda , neste caso para o
print
método interno, como o seguinte :Chamando vários métodos quando o botão é pressionado
Sem argumentos
Você também pode conseguir isso usando a
lambda
declaração, mas é considerada uma prática ruim e, portanto, não a incluirei aqui. A boa prática é definir um método separadomultiple_methods
, que chame os métodos desejados e, em seguida, defina-o como retorno de chamada ao pressionar o botão:Com argumento (s)
Para passar argumentos para métodos que chamam outros métodos, use novamente a
lambda
instrução, mas primeiro:e defina:
Retornando Objeto (s) do retorno de chamada
Além disso, observe que isso
callback
não pode realmentereturn
porque é chamado apenas por dentrobutton_press_handle
ecallback()
não porreturn callback()
. Faz,return
mas não em qualquer lugar fora dessa função. Portanto, você deve modificar os objetos acessíveis no escopo atual.Exemplo completo com modificações globais de objetos
O exemplo abaixo chamará um método que altera
btn
o texto de cada vez que o botão é pressionado:Espelho
fonte
A capacidade do Python de fornecer valores padrão para argumentos de função nos dá uma saída.
Consulte: http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/extra-args.html
Para mais botões, você pode criar uma função que retorna uma função:
fonte
myX
emyY
funciona perfeitamente, muito obrigado.Com base na resposta de Matt Thompsons: uma classe pode ser tornada de chamar, para que possa ser usada em vez de uma função:
fonte
O motivo pelo qual invoca o método imediatamente e pressionar o botão não faz nada é o que
action(somenumber)
é avaliado e seu valor de retorno é atribuído como o comando do botão. Portanto, seaction
imprimir algo para dizer que foi executado e retornadoNone
, basta executaraction
para avaliar seu valor de retorno eNone
o comando do botão.Para ter botões para chamar funções com argumentos diferentes, você pode usar variáveis globais, embora eu não possa recomendar:
O que eu faria é criar
class
objetos cujos objetos conteriam todas as variáveis necessárias e métodos para alterá-las conforme necessário:fonte
Eu acredito que deveria consertar isso
fonte
A melhor coisa a fazer é usar o lambda da seguinte maneira:
fonte
Estou extremamente atrasado, mas aqui está uma maneira muito simples de conseguir isso.
Você simplesmente quebra a função que deseja usar em outra função e chama a segunda função ao pressionar o botão.
fonte
var1
evar2
no módulo principal, você pode pularfunction1
em tudo e colocarprint
declaração emfunction2
. Você se refere a outras situações que eu não entendo?Os lambdas estão todos muito bem, mas você também pode tentar isso (que funciona em um loop for btw):
Isso funciona porque quando a ligação é definida, uma tecla pressionada passa o evento como argumento. Você pode chamar os atributos do evento como
event.char
se fossem "1" ou "UP". Se você precisar de um argumento ou vários argumentos além dos atributos do evento. basta criar um dicionário para armazená-los.fonte
Também já encontrei esse problema antes. Você pode apenas usar lambda:
fonte
Use um lambda para passar os dados de entrada para a função de comando, se você tiver mais ações a serem executadas, como esta (tentei torná-lo genérico, basta adaptar):
Isso passará as informações do evento para a função do botão. Pode haver mais maneiras pitonesas de escrever isso, mas funciona para mim.
fonte
JasonPy - algumas coisas ...
se você apertar um botão em um loop, ele será criado repetidas vezes ... o que provavelmente não é o que você deseja. (talvez seja) ...
O motivo pelo qual sempre obtém o último índice é que os eventos lambda são executados quando você clica neles - não quando o programa é iniciado. Não tenho certeza de 100% do que você está fazendo, mas talvez tente armazenar o valor quando for criado e depois chame-o mais tarde com o botão lambda.
por exemplo: (não use esse código, apenas um exemplo)
então você pode dizer ....
espero que isto ajude!
fonte
Uma maneira simples seria configurar
button
comlambda
a seguinte sintaxe:fonte
Para a posteridade: você também pode usar classes para obter algo semelhante. Por exemplo:
O botão pode ser simplesmente criado por:
Essa abordagem também permite que você altere os argumentos da função definindo, por exemplo
instance1.x = 3
.fonte
Você precisa usar
lambda:
fonte
Use lambda
resultado:
fonte