[Python] Combobox throwing error even though the mainwindow exists

Discussão em 'Python' iniciado por Stack, Abril 24, 2025.

  1. Stack

    Stack Membro Participativo

    Here is my main code

    import ttkbootstrap as ttk
    from random import choice, choices
    import csv
    from Login import Login
    login = Login()
    login.login_gui()
    user = login.authenticated_user
    if user:
    with open('tanishStock_data.csv') as sheet:
    reader = list(csv.DictReader(sheet))
    day = int(reader[-1]['Day'])
    cash = float(reader[-1]['Cash'])
    stocks = {"reliance":float(reader[-4]['Price']), "tata motors":float(reader[-3]['Price']), "itc":float(reader[-2]['Price']), "mahindra":float(reader[-1]['Price'])}
    labels = {} #stores stock_name:it's price_label (refer to line 108)
    holdings = {} #stock : {quantity, price, value}
    def update_label(label, text, fg=None):
    label.configure(text=text, foreground = fg)
    portfolio_window = None
    def bull_run(stock):
    inc_or_dec = choices([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], weights=[20, 30, 10, 8, 7, 4, 3, 2, 2, 1])[0]
    stocks[stock] = stocks[stock] * inc_or_dec / 100 + stocks[stock]
    def bear_run(stock):
    inc_or_dec = choices([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], weights=[20, 30, 10, 8, 7, 4, 3, 2, 2, 1])[0]
    stocks[stock] = stocks[stock] - stocks[stock] * inc_or_dec / 100
    def simulate_stocks():
    for stock in stocks:
    randomizer = choice(["plus", "minus"])
    if randomizer == "plus":
    bull_run(stock)
    elif randomizer == "minus":
    bear_run(stock)
    else:
    print("error encountered")
    break
    update_prices()
    main_window.after(5000, simulate_stocks)
    def update_prices():
    for stock_name, label in labels.items():
    price = float(label.cget("text")) #gets the price out of the price_label
    if price > stocks[stock_name]:
    update_label(label, f"{stocks[stock_name]:.2f}", fg = "red")
    else:
    update_label(label, f"{stocks[stock_name]:.2f}", fg = "#228B22")
    def buy_stock():
    global cash
    stock = vvariable.get().strip().lower()
    try:
    quantity = int(entry_quantity_price.get())
    except ValueError:
    update_label(quantity_warning, "*Enter a valid quantity")
    return
    if stock in stocks:
    total_cost = quantity * stocks[stock]
    if total_cost > cash:
    update_label(quantity_warning, "*Not enough cash")
    elif quantity <= 0 or quantity > 10000:
    update_label(quantity_warning,"*Quantity should be between 1 and 10000")
    else:
    update_label(quantity_warning, "")
    update_label(stock_warning, "")
    if stock not in holdings:
    holdings[stock] = {"quantity": 0, "price": 0, "value": 0}
    holdings[stock]["price"] = (stocks[stock] * quantity + holdings[stock]["price"] * holdings[stock]["quantity"])/(quantity + holdings[stock]["quantity"])
    holdings[stock]["quantity"] += quantity
    holdings[stock]["value"] = holdings[stock]["quantity"] * holdings[stock]["price"]
    cash -= total_cost
    update_label(cash_display, f"CASH: {cash:.2f}")
    else:
    update_label(stock_warning, "*No such stock exists")
    def sell_stock():
    global cash
    stock = vvariable.get().strip().lower()
    try:
    quantity = int(entry_quantity_price.get())
    except ValueError:
    update_label(quantity_warning, "*Enter a valid quantity")
    return
    if stock in holdings:
    if quantity <= 0 or quantity > holdings[stock]["quantity"]:
    update_label(quantity_warning, "*Invalid quantity")
    else:
    update_label(quantity_warning, "")
    update_label(stock_warning, "")
    holdings[stock]["quantity"] -= quantity
    sell_value = quantity * stocks[stock]
    cash += sell_value
    update_label(cash_display, f"CASH: {cash:.2f}")
    holdings[stock]["value"] = holdings[stock]["quantity"] * holdings[stock]["price"]
    if holdings[stock]["quantity"] == 0:
    del holdings[stock]
    else:
    stock_warning.config(text="*You don't own this stock")
    def stock_data_writer(real_day): # writes stock data in csv file
    with open('tanishStock_data.csv', mode ='a', newline ='') as sheet:
    writer = csv.DictWriter(sheet, fieldnames = ['Day', 'Stock', 'Price', 'Cash'])
    for stock in stocks:
    writer.writerow({'Day' : real_day, 'Stock' : stock, 'Price' : f'{stocks[stock]:.2f}', 'Cash' : f'{cash:.2f}'})
    def day_system(): #manages day system in the stock simulator
    global day
    day += 1
    stock_data_writer(day)
    update_label(day_display, text = f"DAY : {day}", fg = "red")
    main_window.after(20000, lambda: day_system())
    def clickable_stocks(stockname, stockprice):
    entry_stock_entry.delete(0, ttk.END)
    entry_quantity_price.delete(0, ttk.END)
    entry_stock_entry.insert(0, stockname)
    entry_quantity_price.insert(0, stockprice)
    def show_portfolio():
    global portfolio_window

    # Destroy the existing portfolio window if it exists
    if portfolio_window:
    portfolio_window.destroy()

    # Create new portfolio window
    portfolio_window = ttk.Toplevel(main_window)
    portfolio_window.title("PORTFOLIO")
    portfolio_window.geometry("420x300")
    portfolio_window.resizable(False, False)

    # Create canvas and scrollbar
    canvas = ttk.Canvas(portfolio_window)
    scrollbar = ttk.Scrollbar(portfolio_window, orient="vertical", command=canvas.yview)
    canvas.configure(yscrollcommand=scrollbar.set)

    # Create a frame inside the canvas
    canvas_frame = ttk.Frame(canvas)
    canvas.create_window((0, 0), window=canvas_frame, anchor="nw")

    # Pack the scrollbar and canvas
    scrollbar.pack(side="right", fill="y")
    canvas.pack(side="left", fill="both", expand=True)

    def update_portfolio_window():
    # Clear the frame before updating
    for widget in canvas_frame.winfo_children():
    widget.destroy()
    row_num = 2
    cash_label = ttk.Label(canvas_frame, text=f"CASH: {cash:.2f}", font=("arial", 13, "bold"),foreground="green")
    cash_label.grid(row=0, column=0, padx=10, pady=10, sticky="w")
    upper_divider = ttk.Label(canvas_frame, text="_" * 80)
    upper_divider.grid(row=1, column=0, columnspan=2, padx=10)
    if holdings:
    for stock, data in holdings.items():
    stock_name = ttk.Label(canvas_frame, text=stock.title(), font=("arial", 15))
    purchase_data = ttk.Label(canvas_frame,
    text=f"Qty: {data['quantity']} | Price: {data['price']:.2f}",
    font=("arial", 8))
    current_value = ttk.Label(canvas_frame, text=f"Value: {data['value']:.2f}", font=("arial", 13),foreground="green")
    stock_name.grid(row=row_num, column=0, padx=10, pady=5, sticky="w")
    purchase_data.grid(row=row_num + 1, column=0, padx=10, sticky="w")
    current_value.grid(row=row_num + 1, column=1, padx=10, sticky="e")

    row_num += 3
    else:
    no_holdings_label = ttk.Label(canvas_frame, text="No holdings yet.", font=("arial", 12))
    no_holdings_label.grid(row=row_num, column=0, columnspan=2, pady=50)
    close_button = ttk.Button(canvas_frame, text="Close", command=portfolio_window.destroy)
    close_button.grid(row=row_num + 1, column=1, sticky="e", padx=10, pady=10)
    canvas_frame.update_idletasks()
    canvas.config(scrollregion=canvas.bbox("all"))
    update_portfolio_window()
    main_window = ttk.Window(themename = "darkly")


    def on_destroy():
    print("Main window is being destroyed.")
    main_window.destroy()


    main_window.protocol("WM_DELETE_WINDOW", on_destroy)

    main_window.geometry("600x500")
    main_window.title("Tanish Stock Exchange")
    vvariable = ttk.StringVar()
    header = ttk.Label(main_window, text = "TSE", font=("arial", 20), foreground="blue")
    header.pack()
    day_display = ttk.Label(main_window, text = f"DAY : {day}", font = ("arial", 15), foreground='red')
    day_display.place(x = 260, y = 300)
    y_position = 80
    stock_entry = ttk.Label(main_window, text ="STOCK: ", font=("arial", 15, "bold"))
    stock_entry.place(x = 300, y = 80)
    stock_warning = ttk.Label(main_window, text = "", font=("arial", 7), foreground="red")
    stock_warning.place(x = 400, y=110)
    stock_quantity = ttk.Label(main_window, text ="quantity: ", font=("arial", 15, "bold"))
    stock_quantity.place(x = 300, y = 120)
    quantity_warning = ttk.Label(main_window, text = "", font=("arial", 7), foreground="red")
    quantity_warning.place(x = 400, y=150)
    entry_stock_entry = ttk.Combobox(master = main_window, values = ["reliance", "tata motors", "itc", "mahindra"], textvariable = vvariable)
    entry_stock_entry.place(x = 400, y = 83)
    entry_quantity_price = ttk.Entry(main_window)
    entry_quantity_price.place(x = 400, y = 125)
    buy = ttk.Button(main_window, text="BUY", style="success", width=7, padding=(20, 10), command = buy_stock)
    buy.place(x = 470, y = 170)
    sell = ttk.Button(main_window, text="SELL",style="danger", width=7, padding=(20, 10), command = sell_stock)
    sell.place(x = 370, y = 170)
    portfolio = ttk.Button(main_window, text="Portfolio",style = "primary",padding = (20, 10),command=show_portfolio)
    portfolio.place(x=20,y=20)
    cash_display = ttk.Label(main_window, text = f"CASH: {cash}", font=("arial", 13, "bold"),foreground="blue")
    cash_display.place(x=410, y=30)
    for stock in stocks:
    stock_label = ttk.Label(main_window, text=f"{stock.title()}:", font=("arial", 15, "bold"), foreground="#4682B4")
    stock_label.place(x=20, y=y_position)
    price_label = ttk.Label(main_window, text=f"{stocks[stock]}", font=("arial", 15), foreground="green")
    price_label.place(x=150, y=y_position)
    labels[stock] = price_label
    stock_label.bind("<Button-1>", lambda event, stockname=stock: clickable_stocks(stockname, round(cash//float(labels[stockname].cget("text")))))
    y_position += 40
    simulate_stocks()
    day_system()
    main_window.mainloop()


    You might be wondering what is the login class so here it is:

    import ttkbootstrap as ttk
    import json
    import bcrypt
    import os

    class Login:
    def __init__(self, username=None, password=None):
    self.username = username
    self.password = password
    self.authenticated_user = False

    def __str__(self):
    return "Login class made for login purposes in every project."

    def display_message(self, message_label, message, color="red"):
    message_label.config(text=message, foreground=color)

    def authenticate_user(self, username, password, window):
    self.username = username.get().strip().lower()
    self.password = password.get().strip().encode("utf-8")

    self.display_message(self.login_message_label, "")

    try:
    with open('User_data.json', 'r+') as user_data:
    data = json.load(user_data)

    for user in data:
    if user["username"] == self.username:
    if bcrypt.checkpw(self.password, user["password"].encode("utf-8")):
    self.display_message(self.login_message_label, "Login successful!", "green")
    window.destroy()
    self.authenticated_user = True
    return
    else:
    self.display_message(self.login_message_label, "Invalid password.")
    return
    salt = bcrypt.gensalt()
    hashed_pass = bcrypt.hashpw(self.password, salt).decode("utf-8")
    new_entry = {"username": self.username, "password": hashed_pass}
    data.append(new_entry)
    user_data.seek(0)
    json.dump(data, user_data, indent=4)
    user_data.truncate()
    self.create_user_stock_file(self.username)
    self.display_message(self.login_message_label, "User added successfully!", "green")
    window.destroy()
    self.authenticated_user = True
    except FileNotFoundError:
    self.display_message(self.login_message_label, "Server error")
    except json.JSONDecodeError:
    self.display_message(self.login_message_label, "Server error")

    def create_user_stock_file(self, username):
    filename = f"{username}stock.csv"
    if not os.path.exists(filename):
    with open(filename, 'w') as file:
    file.write("StockName,Quantity,Price\n")

    def login_gui(self):
    login_window = ttk.Window(themename="darkly")
    login_window.title("TSA Login")
    login_window.geometry("400x250")

    ttk.Label(login_window, text="Welcome to TSA", font=("arial", 17, "bold")).pack()

    ttk.Label(login_window, text="Username: ", font=("arial", 12)).place(x=20, y=50)
    login_username_entry = ttk.Entry(login_window, width=30)
    login_username_entry.place(x=120, y=47)

    ttk.Label(login_window, text="Password: ", font=("arial", 12)).place(x=20, y=100)
    login_password_entry = ttk.Entry(login_window, show="*", width=30)
    login_password_entry.place(x=120, y=97)

    self.login_message_label = ttk.Label(login_window, text="", font=("arial", 10))
    self.login_message_label.place(x=20, y=130)

    ttk.Button(login_window, text="Login", style="primary-outline", width=13, command=lambda: self.authenticate_user(login_username_entry, login_password_entry, login_window)).place(x=160, y=160)

    login_window.mainloop()


    So don't focus on the json or csv files when I run my main code I log in and it successfully logs in, I hardcoded the csv file for now for my ease, so when I run the code it successfully opens the log in gui, after logging in successfully the window is destroyed and I expect it to run the code after it but this error occurs:

    Traceback (most recent call last):
    File "D:\Users\SYSTEM H424\Desktop\Tanish\FUN\main.py", line 196, in <module>
    entry_stock_entry = ttk.Combobox(master = main_window, values = ["reliance", "tata motors", "itc", "mahindra"], textvariable = vvariable)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "D:\Users\SYSTEM H424\Desktop\Tanish\FUN\.venv\Lib\site-packages\ttkbootstrap\style.py", line 4941, in __init__
    func(self, *args, **kwargs)
    File "C:\Users\SYSTEM H424\AppData\Local\Programs\Python\Python312\Lib\tkinter\ttk.py", line 677, in __init__
    Entry.__init__(self, master, "ttk::combobox", **kw)
    File "D:\Users\SYSTEM H424\Desktop\Tanish\FUN\.venv\Lib\site-packages\ttkbootstrap\style.py", line 4960, in __init__
    ttkstyle = Bootstyle.update_ttk_widget_style(
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File "D:\Users\SYSTEM H424\Desktop\Tanish\FUN\.venv\Lib\site-packages\ttkbootstrap\style.py", line 5050, in update_ttk_widget_style
    builder_method(builder, widget_color)
    File "D:\Users\SYSTEM H424\Desktop\Tanish\FUN\.venv\Lib\site-packages\ttkbootstrap\style.py", line 1215, in create_combobox_style
    arrowsize=self.scale_size(12),
    ^^^^^^^^^^^^^^^^^^^
    File "D:\Users\SYSTEM H424\Desktop\Tanish\FUN\.venv\Lib\site-packages\ttkbootstrap\style.py", line 1116, in scale_size
    winsys = self.style.master.tk.call("tk", "windowingsystem")
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    _tkinter.TclError: can't invoke "tk" command: application has been destroyed


    I am helpless now after like 3 hours I don't understand why it is being triggered because like the gui is created. Also I tried to debug it added print statements and even used .protocall() but nothing helps even chat gpt says everything is fine with your code and the issue may lie in the library itself, it suggests me to rebuild the whole application. I am a beginner and it sounds too much boring and hectic to rebuild it so if possible can anyone solve my issue. I previously had both sign in and log in interface which could swap between each other but I discarded it in hope to solve the error

    Continue reading...

Compartilhe esta Página