Tkinter: Закрытие предыдущего окна Toplevel после повторного нажатия на кнопку(при создании нового)

Рейтинг: 0Ответов: 1Опубликовано: 27.08.2023

В программе есть кнопка "Расчёт" при ее нажатии выводится ежемесячный платёж по кредиту, в отдельном окне должен открываться график платежей, при этом при повторном нажатии (в том числе без изменения условий) на "Расчёт" предыдущее окно с графиком платежей (def table_window()) остается. Необходимо, чтобы при повторном нажатии появлялся новый root3 (т.е. график платежей) предыдущий root3 удалялся(закрывался).

Решение подобной проблемы нашел здесь --> https://stackoverflow.com/questions/52369623/close-existing-toplevel-when-a-new-is-created-tkinter-python-3

Однако использование global в своем коде не позволило решить проблему.

Буду признателен за помощь.

Добавляю минимальный код программы:

import tkinter
from tkinter import *
from tkinter import ttk  # подключаем пакет ttk

root = Tk()
root.title('Ипотечный калькулятор')  # заголовок программы
root.geometry("1020x520+70+100")  # размеры глав окна
root.resizable(False, False)  # фиксируем окно

frame_parametrs = LabelFrame(root, text='Параметры заявки', width=250, height=350)
frame_parametrs.place(x=10, y=20)
final_rate = 0.125/12 # ставка по кредиту

def Calculate():
    sum_v = float(sum_field.get().replace(' ', '').replace(',', '.')) if len(
        sum_field.get()) > 0 else 0  # значение суммы кредита
    time_v = float(time_box.get()) if len(
        time_box.get()) > 0 else 0  # значение срока кредитования, лет
    amount = round((sum_v * final_rate) / (1 - (1 / (1 + final_rate) ** (time_v * 12))), 2)
    Label(text=(f'Ежемесячный платёж: {amount}')).place(x=300, y=300)

    def table_window():
        root3 = tkinter.Toplevel(root)
        root3.title('Платёжный календарь')
        root3.geometry("500x500+1100+100")
        columns = ("month", "loan_value", "payment", "insert", "principle", "new_value")  # определяем столбцы
        tree = ttk.Treeview(root3, columns=columns, show="headings") #таблица
        tree.pack(fill=BOTH, expand=1) #  местоположение таблицы
        # определяем заголовки
        tree.heading("month", text="Месяц")
        tree.heading("loan_value", text="Размер кредита")
        tree.heading("payment", text="Ежемесячный платеж")
        tree.heading("insert", text="Процент")
        tree.heading("principle", text="Основной долг")
        tree.heading("new_value", text="Остаток по кредиту")
        value, pmt_yrs, rate, payment = sum_v, time_v, final_rate, amount
        n = 0
        while value > 0:
            n += 1
            interest = (value * rate)
            principle = payment - interest
            if value - payment < 0:
                principle = value
            rows = tuple([n, round(value, 2), round(payment, 2), round(interest, 2), round(principle, 2),
                          round(value - principle, 2)])
            tree.insert("", END, values=rows)
            value = value - principle
    return table_window()


sumvalue = StringVar()
sumvalue.set(int(300_000))
timevalue = StringVar()
timevalue.set(int(3))

def only_digit(text):  # запрет на ввод алфавитных данных в entry сумме и целе кредитования
    result_digit = text.isdigit() or text.isspace() or text in (',', '.')
    return result_digit

# ---------------------- сумма кредита ----------------------#
sum_credit = ttk.Label(frame_parametrs, width=22, text='Сумма кредита', font=("Arial", 11, 'bold'), relief="flat",
                       background='#E0FFFF',
                       foreground="#104E8B", padding=2)  # создаем текст "сумма кредита"
sum_credit.place(x=20, y=110)
sum_field = ttk.Entry(frame_parametrs, textvariable=sumvalue, width=26, font=('Arial', 11, 'bold'), validate="key",
                      validatecommand=(root.register(only_digit), '%S'))  # создаем поле сумма кредита
sum_field.place(x=20, y=130, width=200)

# ---------------------- срок кредита spinbox ----------------------#
name_time = ttk.Label(frame_parametrs, text='Срок кредита, лет', font=("Arial", 11, 'bold'), relief="flat",
                      background="#E0FFFF",
                      foreground="#104E8B", padding=2)
name_time.place(x=20, y=210)
time_box = ttk.Spinbox(frame_parametrs, textvariable=timevalue, from_=3, to=30, font=('Arial', 11, 'bold'),
                       validate="key",
                       validatecommand=(root.register(only_digit), '%S'))
time_box.place(x=20, y=230, width=200)

result = ttk.Button(text="Расчёт", command= lambda : [Calculate()], style='Color.TButton')  # добавили кнопку расчёт и параметры
result.place(x=10, y=420, width=250, height=40)  # отображение кнопки расчёт по заданным параметрам

root.mainloop()

Ответы

▲ 0Принят

Используя дзен python

Плоское лучше, чем вложенное. wiki

Сначала вытащим создание окна toplevel из функции Calculate. И затем легко применяется решение, которое вы нашли по ссылке.

import tkinter
from tkinter import *
from tkinter import ttk  # подключаем пакет ttk


root3 = None


def Calculate():
    sum_v = float(sum_field.get().replace(' ', '').replace(',', '.')) if len(
        sum_field.get()) > 0 else 0  # значение суммы кредита
    time_v = float(time_box.get()) if len(
        time_box.get()) > 0 else 0  # значение срока кредитования, лет
    amount = round((sum_v * final_rate) / (1 - (1 / (1 + final_rate) ** (time_v * 12))), 2)
    Label(text=(f'Ежемесячный платёж: {amount}')).place(x=300, y=300)
    table_window(sum_v, time_v, amount)

def table_window(sum_v, time_v, amount):
    global root3
    if root3 is not None:
        root3.destroy()
    root3 = tkinter.Toplevel(root)
    root3.title('Платёжный календарь')
    root3.geometry("500x500+1100+100")
    columns = ("month", "loan_value", "payment", "insert", "principle", "new_value")  # определяем столбцы
    tree = ttk.Treeview(root3, columns=columns, show="headings") #таблица
    tree.pack(fill=BOTH, expand=1) #  местоположение таблицы
    # определяем заголовки
    tree.heading("month", text="Месяц")
    tree.heading("loan_value", text="Размер кредита")
    tree.heading("payment", text="Ежемесячный платеж")
    tree.heading("insert", text="Процент")
    tree.heading("principle", text="Основной долг")
    tree.heading("new_value", text="Остаток по кредиту")
    value, pmt_yrs, rate, payment = sum_v, time_v, final_rate, amount
    n = 0
    while value > 0:
        n += 1
        interest = (value * rate)
        principle = payment - interest
        if value - payment < 0:
            principle = value
        rows = tuple([n, round(value, 2), round(payment, 2), round(interest, 2), round(principle, 2),
                      round(value - principle, 2)])
        tree.insert("", END, values=rows)
        value = value - principle


def only_digit(text):  # запрет на ввод алфавитных данных в entry сумме и целе кредитования
    result_digit = text.isdigit() or text.isspace() or text in (',', '.')
    return result_digit



root = Tk()
root.title('Ипотечный калькулятор')  # заголовок программы
root.geometry("1020x520+70+100")  # размеры глав окна
root.resizable(False, False)  # фиксируем окно

frame_parametrs = LabelFrame(root, text='Параметры заявки', width=250, height=350)
frame_parametrs.place(x=10, y=20)
final_rate = 0.125/12 # ставка по кредиту

sumvalue = StringVar()
sumvalue.set(int(300_000))
timevalue = StringVar()
timevalue.set(int(3))



# ---------------------- сумма кредита ----------------------#
sum_credit = ttk.Label(frame_parametrs, width=22, text='Сумма кредита', font=("Arial", 11, 'bold'), relief="flat",
                       background='#E0FFFF',
                       foreground="#104E8B", padding=2)  # создаем текст "сумма кредита"
sum_credit.place(x=20, y=110)
sum_field = ttk.Entry(frame_parametrs, textvariable=sumvalue, width=26, font=('Arial', 11, 'bold'), validate="key",
                      validatecommand=(root.register(only_digit), '%S'))  # создаем поле сумма кредита
sum_field.place(x=20, y=130, width=200)

# ---------------------- срок кредита spinbox ----------------------#
name_time = ttk.Label(frame_parametrs, text='Срок кредита, лет', font=("Arial", 11, 'bold'), relief="flat",
                      background="#E0FFFF",
                      foreground="#104E8B", padding=2)
name_time.place(x=20, y=210)
time_box = ttk.Spinbox(frame_parametrs, textvariable=timevalue, from_=3, to=30, font=('Arial', 11, 'bold'),
                       validate="key",
                       validatecommand=(root.register(only_digit), '%S'))
time_box.place(x=20, y=230, width=200)

result = ttk.Button(text="Расчёт", command= lambda : [Calculate()], style='Color.TButton')  # добавили кнопку расчёт и параметры
result.place(x=10, y=420, width=250, height=40)  # отображение кнопки расчёт по заданным параметрам

root.mainloop()