I’m trying to write a simple GUI for my research group project, this is a basic layout. Amongst other things I need to include a “set limits” for fitting procedure. For this I’ve created a function linked to a mpl Button, which runs a esimple Tk window with Entries.
When I press the button the Tk window appears alright but then immediately freezes both windows so I’m not even able to close them.
Here’s an example which reproduces the error for me. (Python 3.11, macOS 14.4.1 (23E224)). For this particular example program works fine with changing background to “TkAgg”, but in a real scenario it can’t handle the main GUI and is really slow.
BTW: If I don’t create main = tk.Tk() widget the program crashes immediately.
I’m very much a newbie in GUI dev, so please point to obvious mistakes. Am I doing something wrong or it’s just not supposed to work like this?
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Button
import matplotlib
import tkinter as tk
def get_lims(l):
global lims
lims = l
root = tk.Tk()
root.geometry("1100x230")
def converter(s, m):
try:
x = float(s)
except ValueError:
x = np.inf * (m - 0.5)
return x
def back_converter(x):
if np.abs(x) < np.inf:
return str(x)
else:
return ''
def submit():
global lims
for i in range(len(inputs)):
lims[i, 0] = converter(inputs[i, 0].get(), 0)
lims[i, 1] = converter(inputs[i, 1].get(), 1)
else:
root.destroy()
lim_labs = ['x ', 'y ', 'm ', 'r ', 'q ', 'PA ', 'b ']
p_inputs = []
e_inputs = []
s_inputs = []
labelp = tk.Label(root, text='PSF', font=('calibre', 15, 'bold'))
labelp.grid(row=0, column=0, columnspan=3)
labele = tk.Label(root, text='Exponent', font=('calibre', 15, 'bold'))
labele.grid(row=0, column=3, columnspan=3)
labels = tk.Label(root, text='Sérsic', font=('calibre', 15, 'bold'))
labels.grid(row=0, column=6, columnspan=3)
for i in range(3):
label = tk.Label(root, text=lim_labs[i], font=('calibre', 13))
p_inputs.append([tk.Entry(root, font=('calibre', 10, 'normal')),
tk.Entry(root, font=('calibre', 10, 'normal'))])
label.grid(row=i + 1, column=0, padx=(10, 0))
p_inputs[i][0].grid(row=i + 1, column=1)
p_inputs[i][1].grid(row=i + 1, column=2)
for i in range(6):
label = tk.Label(root, text=lim_labs[i], font=('calibre', 13))
e_inputs.append([tk.Entry(root, font=('calibre', 10, 'normal')),
tk.Entry(root, font=('calibre', 10, 'normal'))])
label.grid(row=i + 1, column=3, padx=(10, 0))
e_inputs[i][0].grid(row=i + 1, column=4)
e_inputs[i][1].grid(row=i + 1, column=5)
for i in range(7):
label = tk.Label(root, text=lim_labs[i], font=('calibre', 13))
s_inputs.append([tk.Entry(root, font=('calibre', 10, 'normal')),
tk.Entry(root, font=('calibre', 10, 'normal'))])
label.grid(row=i + 1, column=6, padx=(10, 0))
s_inputs[i][0].grid(row=i + 1, column=7)
s_inputs[i][1].grid(row=i + 1, column=8, padx=(0, 10))
inputs = np.concatenate([p_inputs, e_inputs, s_inputs])
for i in range(len(inputs)):
for j in [0, 1]:
inputs[i, j].insert(0, back_converter(lims[i, j]))
sub_btn = tk.Button(root, text='Submit', command=submit)
sub_btn.grid(row=11, column=4, columnspan=2)
cl_btn = tk.Button(root, text='Close', command=root.destroy)
cl_btn.grid(row=11, column=6, columnspan=3)
for i in range(9):
root.grid_columnconfigure(i, weight=1)
root.mainloop()
matplotlib.use("QTagg")
main = tk.Tk()
main.mainloop()
def get_my_lims(event):
global lims
get_lims(lims)
print(lims)
lims = np.array([[-np.inf, np.inf] for i in range(16)])
limax = plt.axes()
button_limit = Button(limax, 'Set limits')
button_limit.on_clicked(get_my_lims)
plt.show()
lim_labs = ['x ', 'y ', 'm ', 'r ', 'q ', 'PA ', 'b ']
p_inputs = []
e_inputs = []
s_inputs = []
labelp = tk.Label(root, text='PSF', font=('calibre', 15, 'bold'))
labelp.grid(row=0, column=0, columnspan=3)
labele = tk.Label(root, text='Exponent', font=('calibre', 15, 'bold'))
labele.grid(row=0, column=3, columnspan=3)
labels = tk.Label(root, text='Sérsic', font=('calibre', 15, 'bold'))
labels.grid(row=0, column=6, columnspan=3)
for i in range(3):
label = tk.Label(root, text=lim_labs[i], font=('calibre', 13))
p_inputs.append([tk.Entry(root, font=('calibre', 10, 'normal')),
tk.Entry(root, font=('calibre', 10, 'normal'))])
label.grid(row=i + 1, column=0, padx=(10, 0))
p_inputs[i][0].grid(row=i + 1, column=1)
p_inputs[i][1].grid(row=i + 1, column=2)
for i in range(6):
label = tk.Label(root, text=lim_labs[i], font=('calibre', 13))
e_inputs.append([tk.Entry(root, font=('calibre', 10, 'normal')),
tk.Entry(root, font=('calibre', 10, 'normal'))])
label.grid(row=i + 1, column=3, padx=(10, 0))
e_inputs[i][0].grid(row=i + 1, column=4)
e_inputs[i][1].grid(row=i + 1, column=5)
for i in range(7):
label = tk.Label(root, text=lim_labs[i], font=('calibre', 13))
s_inputs.append([tk.Entry(root, font=('calibre', 10, 'normal')),
tk.Entry(root, font=('calibre', 10, 'normal'))])
label.grid(row=i + 1, column=6, padx=(10, 0))
s_inputs[i][0].grid(row=i + 1, column=7)
s_inputs[i][1].grid(row=i + 1, column=8, padx=(0, 10))
inputs = np.concatenate([p_inputs, e_inputs, s_inputs])
for i in range(len(inputs)):
for j in [0, 1]:
inputs[i, j].insert(0, back_converter(lims[i, j]))
sub_btn = tk.Button(root, text='Submit', command=submit)
sub_btn.grid(row=11, column=4, columnspan=2)
cl_btn = tk.Button(root, text='Close', command=root.destroy)
cl_btn.grid(row=11, column=6, columnspan=3)
for i in range(9):
root.grid_columnconfigure(i, weight=1)
root.mainloop()
matplotlib.use("QTagg")
main = tk.Tk()
main.mainloop()
def get_my_lims(event):
global lims
get_lims(lims)
print(lims)
lims = np.array([[-np.inf, np.inf] for i in range(16)])
limax = plt.axes()
button_limit = Button(limax, 'Set limits')
button_limit.on_clicked(get_my_lims)
plt.show()
I’ve tried to do the function in a different module, did not help. Using a different backend doesn’t help the cause either.
Daniil Smirnov is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.