2010-11-21 15 views
3

Ich möchte eine Anzahl von Tkinter-Schaltflächen generieren, die verschiedene Dinge tun. Ich habe diesen Code:Tkinter-Schaltflächen dynamisch generieren

import Tkinter as tk 

for i in range(boardWidth): 
    newButton = tk.Button(root, text=str(i+1), 
     command=lambda: Board.playColumn(i+1, Board.getCurrentPlayer())) 
    Board.boardButtons.append(newButton) 

Wenn boardWidth 5 ist, obwohl ich Tasten bekommen beschriftet 1-5, wenn darauf geklickt wird sie alle tun Board.playColumn (5, Board.getCurrentPlayer()).

Ich brauche die erste Schaltfläche zu Board.playColumn (1, Board.getCurrentPlayer()), die zweite zu Board.playColumn (2, Board.getCurrentPlayer()) und so weiter tun.

Danke für jede Hilfe!

Antwort

8

ich denke, das Problem ist, dass die lambda ist der Endwert von i nach den for Schlaufenenden aufnimmt. Dies soll, dass (nicht getestet) beheben:

import Tkinter as tk 

for i in range(boardWidth): 
    newButton = tk.Button(root, text=str(i+1), 
     command=lambda j=i+1: Board.playColumn(j, Board.getCurrentPlayer())) 
    Board.boardButtons.append(newButton) 

aktualisiert

BTW, das aus dem Wert von i berechnet durch Hinzufügen eines Arguments der lambda Funktion mit einem Standardwert gearbeitet, wenn es erstellt wurde, anstatt Zurückverweisen auf den endgültigen Wert von i durch eine Schließung, wenn der Ausdruck darin später ausgeführt wird.

+0

Yup, das hat funktioniert. Vielen Dank! – rikkit

2

Ihr Problem ist, dass Sie viele lambda Objekte in demselben Namespace erstellen, und diese lambda s verweisen auf Namen im äußeren Bereich. Das heißt, sie werden nicht zu Closures und sie speichern keine Referenzen auf die Objekte, bis später ... Wenn es passiert, beziehen sich alle Lambdas auf den letzten Wert von i.

Versuchen Sie einen Rückruf Fabrik mit beheben, dass:

import Tkinter as tk 

def callbackFactory(b, n): 
    def _callback(): 
     return b.playColumn(n, b.getCurrentPlayer()) 
    return _callback 

for i in range(boardWidth): 
    newButton = tk.Button(root, text=str(i+1), 
     command=callbackFactory(Board, i+1)) 
    Board.boardButtons.append(newButton) 

Eine weitere Idee den aktuellen Wert von i als Standardargument Wert im lambda Objekt zu speichern, anstatt sich auf Schließverhalten der Referenz zu speichern :

for i in range(boardWidth): 
    newButton = tk.Button(root, text=str(i+1), 
     command=lambda x=i: Board.playColumn(x+1, Board.getCurrentPlayer())) 
    Board.boardButtons.append(newButton) 
+0

Versucht Ihr zweites Beispiel, wie von Martineau vorgeschlagen. Danke für die Erklärung, warum das passiert ist! – rikkit

Verwandte Themen