Python tkinterのComboboxを連動させたい!

Pocket

前提

Pythonのtkinterを使用してComboboxを2つ作成しました。
1つ目のComboboxで選択された内容に従って、2つ目のComboboxに設定されている値を変更したいというのが今回のお題です。

サンプルソース

#!/usr/bin/python3

from tkinter import *
from tkinter import ttk

list1 = ['A','B','C','D']
list2 = ['1','2','3','4']

if __name__ == '__main__':
    root = Tk()
    root.title('Sample Program')

    # Frame
    frame = ttk.Frame(root, padding=30)
    frame.grid()

    lavel1 = Label(frame,font=("MS ゴシック",10),text="Select 1 :")
    lavel2 = Label(frame,font=("MS ゴシック",10),text="Select 2 :")
    lavel1.grid(row=0,column=0,sticky=W)
    lavel2.grid(row=1,column=0,sticky=W)

    v1 = StringVar()
    v2 = StringVar()
    cb1 = ttk.Combobox(
        frame, textvariable=v1, 
        values=list1, width=20)
    cb2 = ttk.Combobox(
        frame, textvariable=v2, 
        values=list2, width=20)

    cb1.set(list1[0])
    cb2.set(list2[0])

    cb1.bind(
        '<<ComboboxSelected>>', 
        cb2.set(list2[list1.index(v1.get())]))
    cb1.grid(row=0, column=1)
    cb2.bind(
        '<<ComboboxSelected>>', 
        print('v2=%s' % v2.get()))
    cb2.grid(row=1, column=1)

    root.mainloop()

このサンプルプログラムでは、「Select 1」のコンボボックスを選択しても「Select 2」の値は変化しません。

bindの中で指定しているcb2.set()がファンクションとして処理されていないようです。

結果

以下の様に変更しました。


    cb1.bind(
        '<<ComboboxSelected>>', 
        cb2.set(list2[list1.index(v1.get())]))
    cb1.grid(row=0, column=1)
    cb2.bind(
        '<<ComboboxSelected>>', 
        print('v2=%s' % v2.get()))
    cb2.grid(row=1, column=1)

この部分を以下の様に変更しました。


    cb1.bind(
        '<<ComboboxSelected>>', 
        lambda e: cb2.set(list2[list1.index(v1.get())]))
    cb1.grid(row=0, column=1)
    cb2.bind(
        '<<ComboboxSelected>>', 
        lambda e: print('v2=%s' % v2.get()))
    cb2.grid(row=1, column=1)

cb1.bindで指定しているcb2.set()をlambdaで無名関数とすることで、関数として処理されます。

cb2.baind側のprint()は処理されているのですが、敢えて同様にlambdaで無名関数とすることで、プログラムソースの統一をしていますが、敢えて変更しなくても動作します。

関数を指定するところでは、明確にdefで関数を作るか、lambdaで無名関数として定義することが望ましいということの様です。

引っ掛かったので記録として残しておきます。

コメントを残す

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください