Не завершается программа при закрытии окна tkinter (Python)
Использовал в своей программе библиотеку tkinter. Все источники говорят, что при закрытии всех окон выполнение всей программы должно прерываться. И так раньше и было, но сейчас при закрытии окна, PyCharm показывает, что программа всё ещё запущена и остановить её можно как раз через кнопку стоп. Накосячил ли я где-то в коде или теперь оно всегда так работает?
from sympy import *
from tkinter import *
from tkinter import ttk
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import matplotlib.backends.backend_tkagg as tkagg
import numpy as np
# Задание символов
x, y, z = symbols('x y z')
# Первая производная
def der_1(formula):
return diff(formula, x)
# Вторая производная
def der_2(formula):
return diff(diff(formula, x))
# Метод хорд
def chord_method(formula, a, b, eps, nmax):
iteration_array = [[], [], []]
if formula.subs(x, a) * der_2(formula).subs(x, b) > 0:
return print("Корней нет")
else:
n = 1
x_intermediate = a - (formula.subs(x, a) / (formula.subs(x, b) - formula.subs(x, a))) * (b-a)
iteration_array[0].append(n)
iteration_array[1].append(x_intermediate)
iteration_array[2].append(formula.subs(x, x_intermediate))
while True:
if abs(formula.subs(x, x_intermediate)) > eps:
n += 1
if n > nmax:
print("Превышено количество итераций, программа прервана")
return iteration_array
if formula.subs(x, x_intermediate) != 0:
if formula.subs(x, a) * formula.subs(x, x_intermediate) < 0:
b = x_intermediate
else:
a = x_intermediate
x_intermediate = a - (formula.subs(x, a) / (formula.subs(x, b) - formula.subs(x, a))) * (b - a)
iteration_array[0].append(n)
iteration_array[1].append(x_intermediate)
iteration_array[2].append(formula.subs(x, x_intermediate))
else:
print(iteration_array)
return iteration_array
else:
print(iteration_array)
return iteration_array
# Метод половинного деления
def method_of_half_division(formula, a, b, eps, nmax):
iteration_array = [[], [], []]
if formula.subs(x, a) * formula.subs(x, b) > 0:
return print("Корней нет")
else:
n = 1
x_intermediate = (a+b)/2
iteration_array[0].append(n)
iteration_array[1].append(x_intermediate)
iteration_array[2].append(formula.subs(x, x_intermediate))
while True:
if abs(b-a) > eps:
n += 1
if n > nmax:
print("Превышено количество итераций, программа прервана")
return iteration_array
if formula.subs(x, x_intermediate) != 0:
if formula.subs(x, a) * formula.subs(x, x_intermediate) < 0:
b = x_intermediate
else:
a = x_intermediate
x_intermediate = (a+b)/2
iteration_array[0].append(n)
iteration_array[1].append(x_intermediate)
iteration_array[2].append(formula.subs(x, x_intermediate))
else:
return iteration_array
else:
return iteration_array
# Метод касательных
def tangent_method(formula, a, b, eps, nmax):
iteration_array = [[], [], []]
if formula.subs(x, a) * formula.subs(x, b) > 0:
return print("Корней нет")
else:
if formula.subs(x, a) * der_2(formula).subs(x, 2) > 0:
x_intermediate = a
else:
x_intermediate = b
n = 1
h = - (formula.subs(x, x_intermediate) / der_1(formula).subs(x, x_intermediate))
x_intermediate += h
iteration_array[0].append(n)
iteration_array[1].append(x_intermediate)
iteration_array[2].append(formula.subs(x, x_intermediate))
while True:
if abs(h) > eps:
n += 1
if n > nmax:
print("Превышено количество итераций, программа прервана")
return iteration_array
h = - (formula.subs(x, x_intermediate) / der_1(formula).subs(x, x_intermediate))
x_intermediate += h
iteration_array[0].append(n)
iteration_array[1].append(x_intermediate)
iteration_array[2].append(formula.subs(x, x_intermediate))
else:
return iteration_array
# Окно ошибки
def error_win(name):
err_win = Tk()
err_win.title(name)
err_win.geometry("250*200")
err_label = Label(err_win, text="Корней нет")
err_label.grid(row=0, column=0)
# Создание окна с таблицей решений
def win(result_array, name):
result_win = Tk()
result_win.title(name)
result_win.geometry("600x400")
columns = ("iter", "x", "f_x")
tree = ttk.Treeview(result_win, columns=columns, show="headings")
tree.pack(fill=BOTH, expand=1)
tree.heading("iter", text="Итерация")
tree.heading("x", text="X")
tree.heading("f_x", text="F(X)")
res_array = []
for i in range(len(result_array[0])):
inter_array = [result_array[0][i], "{:.17f}".format(result_array[1][i]), "{:.17f}".format(result_array[2][i])]
res_array.append(inter_array)
for iteration in res_array:
tree.insert("", END, values=iteration)
# Функция, вызываемая при нажатии кнопки "Рассчитать"
def calculate():
formula_string = formula_entry.get()
formula = sympify(formula_string)
a = float(a_entry.get())
b = float(b_entry.get())
eps = float(eps_entry.get())
nmax = int(nmax_entry.get())
x_lpos = int(x_left_entry.get())
x_rpos = int(x_right_entry.get())
y_upos = int(y_up_entry.get())
y_dpos = int(y_down_entry.get())
results = []
# Функции привязанные к флажкам
if chord_var.get() == 1:
try:
iterations, x_values, f_values = chord_method(formula, a, b, eps, nmax)
results.append((iterations, x_values, f_values))
win(chord_method(formula, a, b, eps, nmax), "Метод хорд")
except TypeError:
error_win("Метод хорд")
if tangent_var.get() == 1:
try:
iterations, x_values, f_values = tangent_method(formula, a, b, eps, nmax)
results.append((iterations, x_values, f_values))
win(tangent_method(formula, a, b, eps, nmax), "Метод касательных")
except TypeError:
error_win("Метод касательных")
if bisection_var.get() == 1:
try:
iterations, x_values, f_values = method_of_half_division(formula, a, b, eps, nmax)
results.append((iterations, x_values, f_values))
win(method_of_half_division(formula, a, b, eps, nmax), "Метод половинного деления")
except TypeError:
error_win("Метод половинного деления")
plt.clf()
# Отображение графика функции
x_vals = np.linspace(-10, 10, 1000)
f = lambdify(x, formula, modules=['numpy'])
f_vals = f(x_vals)
plt.plot(x_vals, f_vals, label=formula_string)
ax = plt.gca()
ax.spines['left'].set_position('zero')
ax.spines['bottom'].set_position('zero')
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_major_locator(ticker.MultipleLocator(1))
ax.yaxis.set_major_locator(ticker.MultipleLocator(1))
ax.set_xlim(x_lpos, x_rpos)
ax.set_ylim(y_upos, y_dpos)
# Обновление графика в окне
plt.legend()
canvas.draw()
# Создание основного окна
window = Tk()
window.title("Калькулятор")
window.geometry("1220x600")
# Создание полей ввода и надписей
formula_label = Label(window, text="Формула f(x):")
formula_label.grid(row=0, column=0, sticky="w")
formula_entry = Entry(window)
formula_entry.grid(row=0, column=1)
a_label = Label(window, text="Начальная точка интервала a:")
a_label.grid(row=1, column=0, sticky="w")
a_entry = Entry(window)
a_entry.grid(row=1, column=1)
b_label = Label(window, text="Конечная точка интервала b:")
b_label.grid(row=2, column=0, sticky="w")
b_entry = Entry(window)
b_entry.grid(row=2, column=1)
eps_label = Label(window, text="Требуемая точность Eps:")
eps_label.grid(row=3, column=0, sticky="w")
eps_entry = Entry(window)
eps_entry.grid(row=3, column=1)
nmax_label = Label(window, text="Максимальное количество итераций:")
nmax_label.grid(row=4, column=0, sticky="w")
nmax_entry = Entry(window)
nmax_entry.grid(row=4, column=1)
x_left_lable = Label(window, text="x1")
x_left_entry = Entry(window, width=2)
x_right_lable = Label(window, text="x2")
x_right_entry = Entry(window, width=2)
y_up_lable = Label(window, text="y1")
y_up_entry = Entry(window, width=2)
y_down_lable = Label(window, text="y2")
y_down_entry = Entry(window, width=2)
x_left_entry.grid(row=5, column=5)
x_right_entry.grid(row=5, column=7)
y_up_entry.grid(row=5, column=9)
y_down_entry.grid(row=5, column=11)
x_left_lable.grid(row=5, column=4)
x_right_lable.grid(row=5, column=6)
y_up_lable.grid(row=5, column=8)
y_down_lable.grid(row=5, column=10)
# Создание флажков для выбора метода
method_frame = Frame(window)
method_frame.grid(row=0, column=2, rowspan=5, padx=10)
chord_var = IntVar()
chord_checkbutton = Checkbutton(method_frame, text="Метод хорд", variable=chord_var)
chord_checkbutton.pack(anchor="w")
tangent_var = IntVar()
tangent_checkbutton = Checkbutton(method_frame, text="Метод касательных", variable=tangent_var)
tangent_checkbutton.pack(anchor="w")
bisection_var = IntVar()
bisection_checkbutton = Checkbutton(method_frame, text="Метод половинного деления", variable=bisection_var)
bisection_checkbutton.pack(anchor="w")
# Создание кнопки "Рассчитать"
calculate_button = Button(window, text="Рассчитать", command=calculate)
calculate_button.grid(row=5, column=0, pady=5)
# Создание окна для графика
plot_frame = Frame(window)
plot_frame.grid(row=0, column=3, rowspan=6, padx=10, pady=10)
fig = plt.figure(figsize=(5, 5), dpi=100)
canvas = tkagg.FigureCanvasTkAgg(fig, master=plot_frame)
canvas.get_tk_widget().pack()
plt.gca().set_aspect('equal', adjustable='box')
window.mainloop()
Источник: Stack Overflow на русском