Tkinter의 command option에서 인수를 전달할 때 함수에서 중첩을 정의한다고 생각한대로 움직입니다.

4714 단어 Tkinter파이썬

먼저



파이썬을 공부하기 시작한 지 1 개월 정도 지났고 GUI로 뭔가를 만들고 싶다고 생각 Tkinter에 손을 대었을 때
command option의 거동으로 빠졌기 때문에 비망록적으로 기사로 해 보았습니다.

실현하고 싶은 것




요점은 체크 버튼에 체크를 했다/제외했을 때에, 자신의 좌측에 있는 체크 박스도
동적으로 자동으로 체크가 붙거나 벗어나게 하고 싶었습니다.
실행 환경은 Python3.7입니다.

구현한 코드



우선 아무것도 생각하지 않고 「이것으로 에로!」라고 아래의 코드를 썼습니다만, 예상대로 움직이지 않았습니다.
각 체크 박스에 체크를 넣어도, 그보다 좌측의 체크 박스는 움직이지 않는 것 산의 곁.
import tkinter as tk

#GUI#
root = tk.Tk()

cb = {} #チェックボックスの保管#
cb_val = {} #各チェックボックスの値(BooleanVar)を保管#

#チェックボックスの値を生成#
for i in range(4):
   for j in range(3):
       cb_val[i,j] = tk.BooleanVar()

#チェックボックスがクリックされたときのアクション#
def Check(i,j):
    if cb_val[i,j].get() == True:
        for k in range(j):
            cb_val[i,k].set(True)#自分より左のチェックボックスを自分と同じ状態にする#
    else:
        for k in range(j):
            cb_val[i,k].set(False)#自分より左のチェックボックスを自分と同じ状態にする#

#チェックボックス生成#
for i in range(4):
   for j in range(3):
       cb[i,j] = tk.Checkbutton(text=u"チェックボックス"+ str(i) + "-"+ str(j),\
                                variable=cb_val[i,j],command=Check(i,j))

#アイテム配置
for i in range(4):
   for j in range(3):
       cb[i,j].grid(row=i,column=j)

root.mainloop()

시도한 것



움직이지 않기 때문에 여러가지 조사했습니다만, Checkbutton 의 command otption 는 인수를 건네줄 수 없는 것 같다.
※라고 할까 아마 Tkinter 의 widget 로 command option 를 취할 수 있는 녀석은 전부 인수 건네줄 수 없다?
그렇다면 lambda 사용하면 에이안케라고 생각하고 아래와 같이 수정해 보았습니다만 안 되었습니다.
#チェックボックス生成#
for i in range(4):
   for j in range(3):
       cb[i,j] = tk.Checkbutton(text=u"チェックボックス"+ str(i) + "-"+ str(j),\
                                variable=cb_val[i,j],command=lambda :Check(i,j))

정확하게 말하면, 맨 오른쪽 하단의 체크 박스를 눌렀을 때만 상정 동작을 합니다(한 걸음 전진)
단, 맨 왼쪽 하단, 중간 맨 밑의 체크 박스는 눌러도 체크가 붙지 않게 되었습니다 (한 걸음 후퇴)

무슨 일이야?



원인 분리를 위해 아래와 같이 Check(i,j)print()를 추가합니다.
def Check(i,j):
    print(i)
    print(j)
    if cb_val[i,j].get() == True:
        for k in range(j):
            cb_val[i,k].set(True)#自分より左のチェックボックスを自分と同じ状態にする#
    else:
        for k in range(j):
            cb_val[i,k].set(False)#自分より左のチェックボックスを自分と同じ状態にする#

이 상태에서 command=lambda :Check(i,j) 들어간 체크 박스에 체크를 해 봅니다.



어떤 확인란을 눌러도 3,2가 표시됩니다.
즉, command=lambda :Check(i,j)가 모든 확인란에서 command=lambda :Check(3,2)되어 버렸다는 것을 나타냅니다 (아마
따라서, 다음과 같은 거동이 된다.

・3-2를 체크하면 3-0,3-1도 체크가 들어간다. 이것은 Check(3,2)의 예상 동작
 ・3-0,3-1은 클릭할 수 없다(같이 보인다).
이것은 클릭 한 순간에 Check(3,2)가 실행되어 3-2와 동일한 상태로 변경되기 때문입니다.
 ・0-0부터 2-2까지는 체크하면 자신만 변화한다.
이것은 Check(3,2)가 실행되지만 3-2의 체크 상태는 변화가 없기 때문에

그래서 어쨌든 lambda는 이번에 사용할 수 없을 것 같다.
또, command=Check(i,j) 때에는 다음과 같이 됩니다.


이번에는 코드 실행 시 00~32까지print됩니다.
그래서 command option은 widget 생성시에 한번 실행되는 것을 알았습니다.
덧붙여서, 체크 박스를 클릭해도 아무것도 print되지 않습니다.

즉 어떻게 하면



전혀 모르겠다! ! !
그렇다면 슬프다.

 ・command = Check(i,j) 라고 쓰여져 있는 경우, 실제로 실행되는 것은 Check(i,j)()
코드에서 Check(i,j)()가 정의되지 않았기 때문에 아무 일도 일어나지 않았습니다 (그럼 왜 오류 코드가 나오지 않습니까?
따라서 Check(i,j)() 를 정의해 주면 만사 해결할 생각이 듭니다.
#チェックボックスがクリックされたときのアクション#
def Check(i,j):
    def x():
        if cb_val[i,j].get() == True:
            for k in range(j):
                cb_val[i,k].set(True)#自分より左のチェックボックスを自分と同じ状態にする#
        else:
            for k in range(j):
                cb_val[i,k].set(False)#自分より左のチェックボックスを自分と同じ状態にする#
    return x

#チェックボックス生成#
for i in range(4):
   for j in range(3):
       cb[i,j] = tk.Checkbutton(text=u"チェックボックス"+ str(i) + "-"+ str(j),\
                                variable=cb_val[i,j],command=Check(i, j))
Check(i,j)에 중첩 x()을 정의했습니다.
이제 Check(i,j)()를 정의할 수 있습니다.
위 코드에서 실행하면 예상대로 확인란이 작동했습니다. 했어.

마지막으로



GUI가 간단하게 만들 수 있으므로 Tkinter 매우 편리합니다만,
안쪽이 너무 깊어서 전혀 다루지 않는 느낌이 빠지지 않습니다.

좋은 웹페이지 즐겨찾기