Question

I'm working on some kind of my own "on screen keyboard" in python / tkinter.

I have code like this:

def GetKeyRow(self, num, set):
    if set == 'normal':
        if num == 1:
            return ['1', '2', '3', '4', '5', '6' ,'7', '8', '9' ,'0', '+']
        elif num == 2:
            return ['q', 'w', 'e', 'r', 't', 'y', 'u' ,'i', 'o', 'p']
        elif num == 3:
            return ['a', 's', 'd', 'f', 'g', 'h', 'j' ,'k', 'l', "'"]
        elif num == 4:
            return ['<', 'z', 'x', 'c', 'v', 'b', 'n' ,'m', ',', '.', '-']
    elif set == 'caps':
        if num == 1:
            return ['!', '"', '#', '$', '%', '&', '/', '(', ')', '=', '?']
        elif num == 2:
            return ['Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P']
        if num == 3:
            return ['A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', '*']
        if num == 4:
            return ['>', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', ';', ':', '_']

def RenderKeys(self, keyset):
    for btnRow in range(1,5):
        row = self.GetKeyRow(btnRow, keyset)
        keyCounter = 0
        for key in row:
            btn = Button(self.Level, text=key, command=lambda:self.AppendKey(key), font=("Helvetica", 16), width=3, height=2)
            btn.grid(row=btnRow + 2, column=keyCounter)
            keyCounter += 1

def AppendKey(self, value):
    self.InputFiled.insert(END, value)

It loops out quite nice and my buttons are created, but when i press a button i always get "-" as value (if the set vas 'normal'). This is because the last value for 'key" was "-". If i set it to caps it always appends the textfiled with "_".

How can i set the command=lambda:AppendKey(this button value) in this case?

Was it helpful?

Solution

The variables, used in a lambda are not fixed, but change with the context, where the lambda is defined. You can prevent this by writing:

command = lambda key=key: self.AppendKey(key)

Then you get something like that:

KEYROWS = {
    'normal': [
       '1234567890+',
       'qwertyuiop',
       "asdfghjkl",
       '<zxcvbnm,.-',
    ],
    'caps': [
       '!"#$%&/()=?',
       'QWERTYUIOP',
       'ASDFGHJKL*',
       '>ZXCVBNM;:_',
    ],
}

def RenderKeys(self, keyset):
    rows = self.KEYROWS[keyset]
    for row,keys in enumerate(rows):
        for col, key in enumerate(keys):
            btn = Button(self.Level, text=key, command=lambda key=key:self.AppendKey(key), font=("Helvetica", 16), width=3, height=2)
            btn.grid(row=row + 2, column=col)

def AppendKey(self, value):
    self.InputFiled.insert(END, value)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top