Search code examples
pythonuser-interfacetkinter

Python Tkinter expressions not showing on second GUI screen


I have 2 different .py files, one has the the main Tkinter GUI window and other has a code to run calculator in tkinter GUI, the calculator file when executed alone works fine but when called inside the main Window, no expresion is shown on the main GUI just the buttons .

Main file


import tkinter as tk
from tkinter import ttk
from tkinter import *
import cv2
from PIL import Image, ImageTk


# Function to launch a placeholder camera app
def launch_camera():
    #from totestvideocapture import openCameraMain
    '''
    root = tk.Tk()
    camera_app = CameraApp(root)
    root.protocol("WM_DELETE_WINDOW", lambda: on_closing_camera(root, camera_app))  # Handle window close
    root.mainloop()
    '''

class App:
    def __init__(self, root):
        from totestvideocapture import CameraThread
        self.root = root
        root.title("Tkinter with OpenCV")
        self.label = tk.Label(root, text="Tkinter window")
        self.label.pack()

        # Start the camera thread
        self.camera_thread = CameraThread(self)
        self.camera_thread.start()



def launch_calculator():

    from Calculator_App import CalculatorGUI
    if __name__ == "__main__" :
        root = Tk()
        calculator = CalculatorGUI(root)
        root.mainloop()

    
root = tk.Tk()
root.title("Simple GUI")
root.geometry ("1000x800") # Default WidthxHeight
root.minsize(200,300) # locks the window size so that it can't go under these Width, Height
root.maxsize(1920,1080) # locks the window size so that it can't go over these Width, Height 


style1 = ttk.Style()
style1.configure("Frame1.TFrame", background="lightblue")
frame_interaction = ttk.Frame(root, style="Frame1.TFrame",padding=10, relief="ridge")
frame_interaction.place(x=0, y=0, width = 1536, height = 540)


style2 = ttk.Style()
style2.configure("Frame2.TFrame", background="lightgreen")
frame_face = ttk.Frame(root, style="Frame2.TFrame",padding=10, relief="ridge")
frame_face.place(x=936, y=0, width = 600, height = 250)

style3 = ttk.Style()
style3.configure("Frame3.TFrame", background="lightgreen")
frame_Games = ttk.Frame(root, style="Frame3.TFrame",padding=10, relief="ridge")
frame_Games.place(x=0, y=540, width = 768, height = 540)


style4 = ttk.Style()
style4.configure("Frame4.TFrame", background="red")
frame_VA = ttk.Frame(root, style="Frame4.TFrame",padding=10, relief="ridge")
frame_VA.place(x=768, y=540, width = 768, height = 540)



style5 = ttk.Style()
style5.configure("Frame5.TFrame", background="purple")
frame_Rem = ttk.Frame(root, style="Frame5.TFrame",padding=10, relief="ridge")
frame_Rem.place(x=1536, y=0, width = 384, height = 320)


style6 = ttk.Style()
style6.configure("Frame6.TFrame", background="black")
frame_Health_Data = ttk.Frame(root, style="Frame6.TFrame",padding=10, relief="ridge")
frame_Health_Data.place(x=1536, y=320, width = 384, height = 760)



camera_button = ttk.Button(frame_interaction, text="Interaction")
camera_button.place(relx=0.5, rely=0.5, anchor="center")

camera_button = ttk.Button(frame_face, text="Face")
camera_button.place(relx=0.5, rely=0.5, anchor="center")

camera_button = ttk.Button(frame_Games, text="Games")
camera_button.place(relx=0.5, rely=0.5, anchor="center")

camera_button = ttk.Button(frame_Rem, text="Rem")
camera_button.place(relx=0.5, rely=0.5, anchor="center")

camera_button = ttk.Button(frame_VA, text="VA")
camera_button.place(relx=0.5, rely=0.5, anchor="center")

camera_button = ttk.Button(frame_Health_Data, text="Health Data")
camera_button.place(relx=0.5, rely=0.5, anchor="center")


'''

frame = ttk.Frame(root, padding=10)
frame.grid(column=0, row=0, sticky=(tk.N, tk.S, tk.W, tk.E))
frame.columnconfigure(0, weight=1)
frame.rowconfigure(0, weight=1)


frame = ttk.Frame(root, padding=10)
frame.grid(column=0, row=0, sticky=(tk.N, tk.S, tk.W, tk.E))
frame.columnconfigure(0, weight=1)
frame.rowconfigure(0, weight=1)

'''


# Button to launch the camera
camera_button = ttk.Button(frame_interaction, text="Camera",command=launch_calculator)
camera_button.grid(column=0, row=0, sticky=(tk.N, tk.W, tk.E))


# Start the main event loop
if __name__ == "__main__":
    root.mainloop()

Calculator.py



from tkinter import *

class CalculatorGUI:
    def __init__(self, GUI):
        self.equation = StringVar()
        self.expression = ""
        self.equation.set('enter your expression')
        GUI.configure(background="light green") 
        GUI.title("Simple Calculator") 
        GUI.geometry("265x125") 



        self.expression_field = Entry(GUI, textvariable=self.equation)
        self.expression_field.grid(columnspan=4, ipadx=70)

        buttons = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0',]

        row_val = [2, 2, 2, 3, 3, 3, 4, 4, 4, 5]
        col_val = [0, 1, 2, 0, 1, 2, 0, 1, 2, 0]

        for button_text, row, col in zip(buttons, row_val, col_val):
            button = Button(GUI, text=f' {button_text} ', fg='black', bg='red',
                            command=lambda btn=button_text: self.press(btn), height=1, width=7)
            button.grid(row=row, column=col)

        symbol_buttons = ['+', '-', '*', '/']
        for symbol in symbol_buttons:
            button = Button(GUI, text=f' {symbol} ', fg='black', bg='red',
                            command=lambda sym=symbol: self.press(sym), height=1, width=7)
            button.grid(row=symbol_buttons.index(symbol) + 2, column=3)

        equal = Button(GUI, text=' = ', fg='black', bg='red',
                       command=self.equalpress, height=1, width=7)
        equal.grid(row=5, column=2)

        clear_btn = Button(GUI, text='Clear', fg='black', bg='red',
                           command=self.clear, height=1, width=7)
        clear_btn.grid(row=5, column=1)

    def press(self, num):
        self.expression = self.expression + str(num)
        self.equation.set(self.expression)

    def equalpress(self):
        try:
            result = str(eval(self.equation.get()))
            self.equation.set(result)
            self.expression = ""

        except:
            self.equation.set(" error ")
            self.expression = ""
    
    def clear(self):
        self.expression = ""
        self.equation.set("")


if __name__ == "__main__":
    root = Tk()
    calculator = CalculatorGUI(root)
    root.mainloop()

I was expecting to run the calculator app on one of the colour coded frames and make a windows like GUI.


Solution

  • When you have two windows Tk() and two mainloop() then it is important to set parent in all elements - even in StringVar() - to show which window should work with these elements.
    If you don't have it then it may work with wrong window and you may not get result.

    And you need StringVar(GUI) in CalculatorGUI to work correctly.


    BTW:

    normally tkinter should have only one window tkinter.Tk() with one mainloop() and other windows should use tkinter.Toplevel() without mainloop(). It allows to access value from one window in another window - and it could get automatically result from CalculatorGUI to main window.