0

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?

RedSmolf
  • 355
  • 3
  • 11
  • https://stackoverflow.com/questions/5767228/why-is-the-command-bound-to-a-button-or-event-executed-when-declared, and https://stackoverflow.com/questions/70770678/generate-button-and-entry-pair-based-on-list-and-have-the-button explain this.Among others, btw. – Menno Hölscher Jan 19 '22 at 12:40
  • The first link only explain why you can't use a parathesis and as stated in the description I know why. Want to know if there is a solution of what the intention of the sample is. The other link lnks to this question. – RedSmolf Jan 19 '22 at 12:51
  • *"I understand why"* If you understand why, you should know how to fix it. Actually the first link in the comment has answer on this case. – acw1668 Jan 19 '22 at 14:40
  • The thread creator in linked post did not have the same problem as me. I understand that the answer might be within all the replies to that post and Menno Hölscher might be right. The solution here was to use "a lambda on a lambda". The linked post would have solved my second problem. – RedSmolf Jan 19 '22 at 15:07

1 Answers1

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.

hussic
  • 1,816
  • 9
  • 10
  • It is absolutely closer! But when running the same code with your addon I get the following output when I click the first button (no matter what I enter in the Entry) "startMotor PY_VAR0 0 1" – RedSmolf Jan 19 '22 at 13:18
  • Ah that is another thing: use `var.get()` to retrieve the value of a tkinter var. – hussic Jan 19 '22 at 14:22
  • Thank you, works like clock! – RedSmolf Jan 19 '22 at 15:02