Załóżmy, że wykonałem następujące czynności Button
z Tkinter w Pythonie:
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)
Metoda action
jest wywoływana po naciśnięciu przycisku, ale co jeśli chciałbym przekazać do niej jakieś argumenty action
?
Próbowałem z następującym kodem:
button = Tk.Button(master=frame, text='press', command=action(someNumber))
Po prostu natychmiast wywołuje metodę, a naciśnięcie przycisku nic nie robi.
Odpowiedzi:
Osobiście wolę używać
lambdas
w takim scenariuszu, ponieważ imo jest bardziej przejrzyste i prostsze, a także nie zmusza do pisania wielu metod opakowujących, jeśli nie masz kontroli nad wywołaną metodą, ale to z pewnością kwestia gustu.Tak byś to zrobił z lambdą (zwróć uwagę, że w module funkcjonalnym jest też implementacja curry, więc możesz też tego użyć):
źródło
partial
działa w tym przypadku."This just invokes the method immediately, and pressing the button does nothing"
?callback=lambda x=x: f(x)
jak wfs = [lambda x=x: x*2 for x in range(5)] ; print [f() for f in fs]
Można to również zrobić za pomocą functools
partial
ze standardowej biblioteki , na przykład:źródło
button = Tk.Button(master=frame, text='press', command=partial(action, arg))
action_with_args = partial(action, arg1, arg2... argN)
Przykład GUI:
Powiedzmy, że mam GUI:
Co się dzieje po naciśnięciu przycisku
Zobacz, że po
btn
naciśnięciu wywołuje własną funkcję, która jest bardzo podobna dobutton_press_handle
w poniższym przykładzie:z:
Możesz po prostu pomyśleć, że
command
opcja powinna być ustawiona jako odwołanie do metody, którą chcemy wywołać, podobnie jakcallback
wbutton_press_handle
.Wywołanie metody ( oddzwonienie ) po naciśnięciu przycisku
Bez argumentów
Więc gdybym chciał
print
coś po wciśnięciu przycisku musiałbym ustawić:Zwrócić szczególną uwagę na brak w
()
zprint
metody, która została pominięta w ten sposób, że: „Jest to metoda, której nazwa Chcę żebyś zadzwonił po naciśnięciu ale . Nie nazywają to po prostu to bardzo natychmiastowy” Jednak nie przekazałem żadnych argumentów,print
więc wydrukowało wszystko, co drukuje, gdy zostanie wywołane bez argumentów.Z argumentami
Teraz Gdybym chciał również przekazać argumenty do metody, którą chcę wywołać po naciśnięciu przycisku, mógłbym skorzystać z funkcji anonimowych, które można utworzyć za pomocą wyrażenia lambda , w tym przypadku dla
print
metody wbudowanej, jak poniżej :Wywołanie wielu metod po naciśnięciu przycisku
Bez argumentów
Możesz to również osiągnąć za pomocą
lambda
stwierdzenia, ale jest to uważane za złą praktykę i dlatego nie będę go tutaj umieszczać. Dobrą praktyką jest zdefiniowanie osobnej metody,multiple_methods
która wywołuje żądane metody, a następnie ustawia ją jako wywołanie zwrotne do przycisku press:Z argumentami
Aby przekazać argument (y) do metody, która wywołuje inne metody, ponownie użyj
lambda
instrukcji, ale najpierw:a następnie ustaw:
Zwracanie obiektów z wywołania zwrotnego
Ponadto zauważ, że
callback
tak naprawdę nie może,return
ponieważ jest wywoływany tylko wewnątrzbutton_press_handle
z,callback()
a nie zreturn callback()
. Czynireturn
ale nie nigdzie poza tą funkcją. Dlatego powinieneś raczej modyfikować obiekty, które są dostępne w bieżącym zakresie.Kompletny przykład z globalnymi modyfikacjami obiektów
Poniższy przykład wywoła metodę, która zmienia
btn
tekst po każdym naciśnięciu przycisku:Lustro
źródło
Zdolność Pythona do zapewnienia domyślnych wartości argumentów funkcji daje nam wyjście.
Zobacz: http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/extra-args.html
Aby uzyskać więcej przycisków, możesz utworzyć funkcję, która zwraca funkcję:
źródło
myX
imyY
działa idealnie, bardzo dziękuję.Opierając się na odpowiedzi Matta Thompsona: klasa może być wywoływana, więc może być używana zamiast funkcji:
źródło
Powodem, dla którego wywołuje metodę natychmiast, a naciśnięcie przycisku nic nie robi, jest to, że
action(somenumber)
jest obliczana, a jej wartość zwracana jest przypisywana jako polecenie dla przycisku. Więc jeśliaction
drukuje coś, co mówi, że zostało uruchomione i wróciNone
, po prostu biegniesz,action
aby oszacować wartość zwracaną i podajeszNone
jako polecenie dla przycisku.Aby mieć przyciski do wywoływania funkcji z różnymi argumentami, możesz użyć zmiennych globalnych, chociaż nie mogę tego polecić:
To, co zrobiłbym, to utworzyć obiekt,
class
którego obiekty zawierałyby wszystkie wymagane zmienne i metody ich zmiany w razie potrzeby:źródło
Myślę, że powinienem to naprawić
źródło
Najlepszą rzeczą do zrobienia jest użycie lambda w następujący sposób:
źródło
Jestem bardzo spóźniony, ale tutaj jest bardzo prosty sposób na osiągnięcie tego.
Po prostu zawijasz funkcję, której chcesz użyć, do innej funkcji i wywołujesz drugą funkcję po naciśnięciu przycisku.
źródło
var1
ivar2
modułu głównego, można pominąćfunction1
w ogóle i umieścićprint
oświadczeniefunction2
. Czy odnosisz się do innych sytuacji, których nie rozumiem?Lambdy są dobre i dobre, ale możesz też spróbować tego (co przy okazji działa w pętli for):
Działa to, ponieważ gdy powiązanie jest ustawione, naciśnięcie klawisza przekazuje zdarzenie jako argument. Możesz wtedy wywołać atrybuty zdarzenia, takie jak
event.char
uzyskanie „1” lub „W GÓRĘ” ect. Jeśli potrzebujesz argumentu lub wielu argumentów innych niż atrybuty zdarzenia. po prostu utwórz słownik, aby je przechowywać.źródło
Z tym problemem też się spotkałem. Możesz po prostu użyć lambda:
źródło
Użyj lambdy, aby przekazać dane wejściowe do funkcji polecenia, jeśli masz więcej działań do wykonania, takich jak to (próbowałem uczynić to ogólnym, więc po prostu dostosuj):
Spowoduje to przekazanie informacji w zdarzeniu do funkcji przycisku. Może być więcej sposobów pisania tego w Pythonie, ale dla mnie to działa.
źródło
JasonPy - kilka rzeczy ...
jeśli włożysz przycisk w pętlę, będzie on tworzony w kółko ... co prawdopodobnie nie jest tym, czego chcesz. (może to jest)...
Powodem, dla którego zawsze pobiera ostatni indeks, są zdarzenia lambda uruchamiane po ich kliknięciu, a nie po uruchomieniu programu. Nie jestem pewien w 100% tego, co robisz, ale może spróbuj zapisać wartość, gdy zostanie utworzona, a następnie wywołaj ją później przyciskiem lambda.
np .: (nie używaj tego kodu, tylko przykład)
wtedy możesz powiedzieć ....
mam nadzieję że to pomoże!
źródło
Jednym prostym sposobem byłoby skonfigurowanie
button
zalambda
pomocą następującej składni:źródło
Dla potomnych: możesz również użyć klas, aby osiągnąć coś podobnego. Na przykład:
Przycisk można następnie po prostu utworzyć za pomocą:
Takie podejście pozwala również na zmianę argumentów funkcji przez np
instance1.x = 3
. Ustawienie .źródło
Musisz użyć
lambda:
źródło
Użyj lambda
wynik:
źródło