Close a tkinter progressbar window while matplotlib window is open

Question:

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()
Asked By: throwaway17434

||

Answers:

You are getting conflicting gui-main loops between the TK you are starting and the TK that plt is start. If you want to use matplotlib with your own gui, you must embed it your self and you can not import pyplot. All the behind the scenes magic that makes the pyplot interface wonderful is what is messing you up here.

For a tutorial see here, for how mpl does the embedding see here.

Also see:

Answered By: tacaswell

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.

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()

This answer was posted as an edit to the question Close a tkinter progressbar window while matplotlib window is open by the OP throwaway17434 under CC BY-SA 3.0.

Answered By: vvvvv
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.