Generate Button and Entry pair based on list and have the Button

I'm trying to create a tkinter GUI that will be used to communicate with a microcontroller.

I want to create a bunch of Button - Entry pairs that each will send a command to the microcontroller together with the input of each Entry (formatted specific to that command).

I want to create the buttons by iterating over a list which contain the button name and a formatting function for the Entry widget.

See the code below for an example.

import tkinter as tk

root = tk.Tk()

class ButtonEntryFrame():
    def __init__(self, parent, params, txtVar) -> None:
        self.txt = params[0]
        self.fn = params[1]
        self.txtVar = txtVar

        self.frame = tk.Frame(parent)
        self.button = tk.Button(self.frame, text=self.txt, command=self.fn(self.txtVar))
        self.entry = tk.Entry(self.frame, textvariable=self.txtVar)

        self.button.pack(side=tk.LEFT)
        self.entry.pack()
        self.frame.grid()


frameInput = tk.Frame(root)
frameInput.pack(side=tk.LEFT)


inputFunctions = [
    ('Func A', lambda x: print(f"startMotor {x} 0 1")),
    ('Func B', lambda x: print(f"stopMotor")),
    ('Func C', lambda x: print(f"increaseSpeed 100 {x} 3"))]

frames = []
for i, params in enumerate(inputFunctions):
    txtVar = tk.StringVar()
    f = ButtonEntryFrame(frameInput, params, txtVar)
    frames.append(f)

root.mainloop()

The code above does not work as I intend it to work. When I run it the lambdas are executed and printed directly. I understand why.

Is it possible to achieve what I want?


Solution 1:

You must do:

self.button = tk.Button(self.frame, text=self.txt, command=lambda: self.fn(self.txtVar))

I added the lambda else self.fnis immediately called.