I am writing a program that does some work and uses matplotlib to plot some data. This can take some time so I set up a progressbar using tkinter. Threading with tkinter was not that easy. I am running the progressbar in the main thread and my working stuff in a substhread. However I can not close the progressbar window after my work is done, because apparently matplotlib does something in the tk root window. I don't know what. I added a minimal example of what I am trying to do. Notice that removing the line "plotsomething()" makes it do what I want: close the progressbar after work is done.
Can you please help me figuring out how I can close the progressbar window without closing the matplotlib windows?
# coding = utf-8
import numpy as np
import matplotlib.pyplot as plt
import tkinter as tk
from tkinter import ttk
import threading, queue
import time
def MAIN():
PB = q.get()
for i in np.arange(10):
time.sleep(0.2)
print(i)
PB.step(10)
PB.update()
print("Done")
def plotsomething():
x = np.linspace(0,10,100)
y = np.sin(x)
plt.plot(x,y)
root = tk.Tk()
root.title("Progress")
PB = ttk.Progressbar(root, orient = "horizontal",length=300, mode = 'determinate')
PB.pack()
q = queue.Queue()
q.put(PB)
plotsomething()
T = threading.Thread(target=MAIN(), name="MAIN")
T.start()
T.join()
plt.show()
EDIT - SOLUTION: I am solving the problem now by drawing every window seperatly by using the matplotlib tk backend. Apparently PyPlot is interfering with the tkinter root windows. See tcaswell's comment for more details and hints. Thank you very much!
import numpy as np
import matplotlib
matplotlib.use('TkAgg')
from numpy import arange, sin, pi
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
import tkinter as tk
from tkinter import ttk
import queue, threading, time
def center_window(window_parent, w=300, h=20):
# get screen width and height
ws = window_parent.winfo_screenwidth()
hs = window_parent.winfo_screenheight()
# calculate position x, y
x = (ws/2) - (w/2)
y = (hs/2) - (h/2)
window_parent.geometry('%dx%d+%d+%d' % (w, h, x, y))
def MAIN():
PB = q.get()
for i in np.arange(10):
time.sleep(0.2)
print(i)
PB.step(10)
PB.update()
print("Done")
root = tk.Tk()
root.wm_title("Embedding in TK")
f = Figure(figsize=(5,4), dpi=100)
a = f.add_subplot(111)
t = arange(0.0,3.0,0.01)
s = sin(2*pi*t)
a.plot(t,s)
a.set_title('Tk embedding')
a.set_xlabel('X axis label')
a.set_ylabel('Y label')
#a tk.DrawingArea
root2 = tk.Tk()
PB = ttk.Progressbar(root2, orient = "horizontal",length=300, mode = 'determinate')
PB.pack()
canvas = FigureCanvasTkAgg(f, master=root)
canvas.show()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
toolbar = NavigationToolbar2TkAgg( canvas, root )
toolbar.update()
canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
root2.iconify()
root2.update()
root2.deiconify()
center_window(root2)
q = queue.Queue()
q.put(PB)
T = threading.Thread(target=MAIN(), name="MAIN")
T.start()
T.join()
root2.quit()
root2.destroy()
tk.mainloop()
See Question&Answers more detail:
os