파이썬 tkinter : 동적으로 버튼을 생성하고, 각 버튼에 대한 이벤트처리기를 lambda 를 사용하여 연결할 때의 문제.

조회수 2988회

i = 0
for f in range(len(machh)): 
    globals()['button{}'.format(f)] = 
        tkinter.Button(frame, 
                       command = lambda : self.Match_Deep_Search(f) )
    # 버튼을 리스트의 크기만큼 만듬 

def Match_Deep_Search(mId):
        print(mId)

machh 라는 리스트에 특정 유저의 전적 기록이 들어있습니다. 게임을 10판을 했으면 리스트에 10개의 id가 있는 식으로요.

for 문으로 machh 리스트의 크기만큼의 버튼을 생성해서 순서에 맞는 버튼을 누르면 해당 순서의 id가 Match_Deep_Search 함수로 넣어지게 하고 싶은데

( 1번째 버튼을 누르면 1번째 id가 함수에 매개변수로 들어가는 식으로 )

f를 매개 변수로 사용하면 최종 f의 크기로 숫자가 고정되더라고요.

이 경우에 특정 버튼이 자신이 몇번째 버튼인지를 알게 해야할것같은데 어떤식으로 구현할수 있을까요? 답변 부탁드립니다.

2 답변

  • 
    from tkinter import Button, Tk
    
    
    class MainWin(Tk):
        def __init__(self, parent):
            Tk.__init__(self, parent)
            self.parent = parent
            self.buttons = {}
            self.dat = ["A", "B", "C", "D"]
            self.init_widgets()
    
        def init_widgets(self):
            for i, d in enumerate(self.dat):
                btn = Button(
                    self,
                    width=10,
                    text=f"{i}-{d}",
                    command=lambda x=i: self.on_click(x),
                )
                btn.grid(row=i, column=0)
                self.buttons[i] = btn
    
        def on_click(self, i):
            print(f"{i} clicked")
    
    
    if __name__ == "__main__":
        app = MainWin(None)
        app.mainloop()
    

    lambda x=i: self.on_clilck(x) 이런 식으로 람다함수에 다른 변수를 도입해서 지정해야 원하는대로 동작하네요.

    globals() 를 이용해서 굳이 동적으로 버튼변수를 생성하는 방법 좋지 않습니다. 제 예제에서처럼 사전(또는 리스트)으로 만들고, 생성된 버튼을 그 안에 넣어 관리하는 것이 훨씬 좋습니다. 버튼이 몇개인지도 금방 알 수 있고 등등. globals() 를 이용해서 변수를 만들고 있다면, 잘못하고 있는 겁니다.

  • f의 크기로 고정된다는게 무슨 뜻인지 모르겠습니다.

    예시가 있었다면 좋을텐데.. 코드를 봤을 때 4번째 기록을 선택했다고 한다면 Match_Deep_Search(mId) 함수가 machh 리스트 요소가 아닌 숫자 4를 출력할 것 같습니다.

    제 생각에는 다음과 같이 변수에 숫자가 아닌 리스트 요소를 넣어줘야 한다고 생각합니다.

    i = 3
    for f in range(len(machh)): 
        if i == f:
            globals()['button{}'.format(f)] = tkinter.Button(frame, command = lambda : self.Match_Deep_Search(machh[f]) )
        # 버튼을 리스트의 크기만큼 만듬 
    def Match_Deep_Search(mId):
            print(mId)
    
    • 이해를 쉽게하기 위해 f 를 적었을뿐 실제로 사용한 코드는 self.Match_Deep_Search(machh[f])가 맞습니다! 문제는 machh 리스트의 최대크기가 5일경우 최종적으로 f의 크기는 0부터 4까지 커져서 반복문이 끝나면 5개의 버튼이 생성되고 f는 4인 상태로 끝나는데 2번째 버튼을 누르던 3번째 버튼을 누르던 f는 4라 machh리스트의 마지막 id만 Match_Deep_Search 함수의 매개 변수로 들어가게 됩니다 ㅠㅠ 알 수 없는 사용자 2021.4.22 13:02
    • 결국 f 의 크기가 고정된다는 뜻은 어떤 버튼을 누르던 리스트의 f번쨰 요소가 매개변수로 사용된다는 이야기 입니다! f = len(machh)-1 로 고정대요 ㅜㅜ 알 수 없는 사용자 2021.4.22 13:08
    • 그러면 클릭했을 때의 변수를 입력받도록 하면 되죠. 초보자 2021.4.22 14:07
    • ..? 알 수 없는 사용자 2021.4.22 14:33

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)