0

In working.py , I get the focused frame using focus().
In calculations.py, I am trying to run some calculations which depends on which frame is focused.
I am calling calculations() on btn which is in main.py.

What I am trying to achieve is that when I click Calculate button,
if e1_frame is focused I should get the addition of 2 numbers and
when e2_frame is focused I should get the multiplication of those 2 numbers.

But instead I get the following error:
TypeError: <lambda>() missing 1 required positional argument: 'e'

main.py

from tkinter import *
from working import create_frames
from calculations import calculations


class MyApp:
    def __init__(self, root):
        self.root = root

        self.var_e1 = StringVar(None)
        self.var_e2 = StringVar(None)
        self.var_lbl = StringVar(None)
        self.var_status_lbl = StringVar(None)

        create_frames(self)

        e1 = Entry(self.e1_frame, textvariable=self.var_e1)
        e2 = Entry(self.e2_frame, textvariable=self.var_e2)
        e1.focus_set()

        e1.pack()
        e2.pack()

        btn = Button(self.btn_frame, text='Calculate', command=lambda e: calculations(self, e))
        btn.pack()

        lbl = Label(self.root, font=20, textvariable=self.var_lbl)
        self.var_lbl.set('0')
        lbl.pack()

        status_lbl = Label(self.root, textvariable=self.var_status_lbl)
        status_lbl.pack(side=BOTTOM)
        self.var_status_lbl.set('Nothing is selected.')

def main():
    root = Tk()
    root.geometry('400x400')
    MyApp(root)
    root.mainloop()


if __name__ == '__main__':
    main()

working.py

from tkinter import *

def focus(self, event):
    if event.widget == self.e1_frame:
        self.var_status_lbl.set(f'First value: {self.var_e1.get()}')
    if event.widget == self.e2_frame:
        self.var_status_lbl.set(f'Second value: {self.var_e2.get()}')
    
def create_frames(self):
    e0_frame = Frame(self.root)
    self.e1_frame = Frame(e0_frame)
    self.e2_frame = Frame(e0_frame)
    
    e0_frame.pack()
    self.e1_frame.pack(side=LEFT)
    self.e2_frame.pack(side=LEFT)

    self.btn_frame = Frame(self.root)
    self.btn_frame.pack(pady=10)

    self.e1_frame.bind('<Enter>', lambda e: focus(self, e))
    self.e2_frame.bind('<Enter>', lambda e: focus(self, e))

calculations.py

from tkinter import *

def calculations(self, event):
    value1 = int(self.var_e1.get())
    value2 = int(self.var_e2.get())

    if event.widget == self.e1_frame:
        result = value1 + value2
    if event.widget == self.e2_frame:
        result = value1 * value2

    result = value1 + value2
    self.var_lbl.set(result)

1 Answers1

0

This line seems problematic to me:

lambda e: calculations(self, e)

While you define a lambda for a button command you set the argument e which commonly stands for event, which refers to an EvenObject produced by tkinter and passed as argument to the bounded function/method.

Enough of the context and lets see how we can fix your code. I would suggest to make calculation an ordinary method and leave that event object for cases where it is more needed. You can simply get which entry has the keyboard focus by calling focus_get(), which can easily replace your event.widget if statement.

import tkinter as tk

def cmd():
    print(root.focus_get())

root = tk.Tk()
e1 = tk.Entry()
e2 = tk.Entry()
b1 = tk.Button(command=cmd)

e1.pack()
e2.pack()
b1.pack()
Thingamabobs
  • 7,274
  • 5
  • 21
  • 54
  • I thought about using this method. But how am I supposed to use this method in my if statements in calculations.py – Milind Khobragade Dec 04 '21 at 08:26
  • @MilindKhobragade `event.widget` would return a widget reference as `focus_get` does. I dont see the problem here. – Thingamabobs Dec 04 '21 at 08:31
  • `focus_get()` is working well with the entries, but not with the frames. In my original code I've several widgets(frames, entries, labels, ComboBoxes) in that frame. And I've many such frames. I don't want to select specific entry from specific frame each time when I calculate. – Milind Khobragade Dec 05 '21 at 08:20
  • @MilindKhobragade then your question isnt clear und you should have pointed that out in your question. – Thingamabobs Dec 05 '21 at 08:21
  • @ Thingamabobs, sorry to say, but I did mention about focused frame widget in my question – Milind Khobragade Dec 05 '21 at 08:50
  • @MilindKhobragade you allready save which frame is entered with `self.var_status_lbl.set`. Why dont you `get` it and compare it in this case? – Thingamabobs Dec 05 '21 at 08:52
  • I tried it like this in `calculations.py`, `if self.var_status_lbl.get() == self.var_e1.get():`, I don't get any errors but nothing happens when I calculate. – Milind Khobragade Dec 05 '21 at 09:24
  • `self.var_status_lbl.set(self.e1_frame)` in `working.py` and then compare it in `calculation.py` like this `if self.var_status_lbl.get() == str(self.e1_frame):` – Thingamabobs Dec 05 '21 at 11:35
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/239841/discussion-between-milind-khobragade-and-thingamabobs). – Milind Khobragade Dec 05 '21 at 11:47