admin管理员组

文章数量:1122832

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 comes

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 amy lie in the library itself, it sugests me to rebuild the whole application. i am a begginer 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

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 comes

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 amy lie in the library itself, it sugests me to rebuild the whole application. i am a begginer 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

Share Improve this question edited 22 hours ago TheLizzard 7,6702 gold badges15 silver badges39 bronze badges asked yesterday user28243057user28243057 1 0
Add a comment  | 

1 Answer 1

Reset to default 0

It may be design/implementation issue of ttkbootstrap.

Suggest to:

  • create only one main window which is initially hidden
  • use ttk.Toplevel() instead of ttk.Window() for login window
  • use .wait_window() instead of .mainloop() to wait for closing of login window
  • resume main window if login successful

Below is a simplified example:

import ttkbootstrap as ttk

class Login:
    def __init__(self):
        self.authenticated_user = False

    def login_gui(self):
        login_window = ttk.Toplevel()  # used ttk.Toplevel() instead of ttk.Window()
        login_window.title('TSA Login')
        login_window.geometry('400x250')

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

        login_window.wait_window() # used wait_window() instead of mainloop()

    def authenticate_user(self, window):
        window.destroy()
        self.authenticated_user = True

# create main window and hidden initially
main_window = ttk.Window(themename='darkly')
main_window.withdraw()

# show the login window
login = Login()
login.login_gui()

if login.authenticated_user:
    main_window.title('Tanish Stock Exchange')
    main_window.geometry('600x500')

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

    main_window.protocol('WM_DELETE_WINDOW', on_destroy)

    stock_entry = ttk.Label(main_window, text='STOCK:', font=('arial', 15, 'bold'))
    stock_entry.place(x=300, y=80)

    vvariable = ttk.StringVar()
    options = ['reliance', 'tata motors', 'itc', 'mahindra']
    entry_stock_entry = ttk.Combobox(main_window, values=options, textvariable=vvariable)
    entry_stock_entry.place(x=400, y=83)

    main_window.deiconify() # resume the main window
    main_window.mainloop()

本文标签: pythoncombobox throwing error even though the mainwindow existsStack Overflow