I want to display a matplotlib figure in a python application with a tkinter GUI. To avoid blocking UI-features while the figure is being created and drawn to the UI, this has to be done in another thread. How do I draw the plot in a different thread than the one containing the tkinter root and frame?
I have tried using the threading module, and managed to create a figure in another thread. However when I try to create a canvas with the figure the application crashes and outputs 'WARNING: QApplication was not created in the main() thread.'
Imports
from tkinter import *
from tkinter import ttk
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from threading import Thread
Everything is in the same class right now. I create the root, mainframe and a button in the constructor
def __init__(self):
# Creates root and mainframe
self.root = Tk()
self.mainframe = ttk.Frame(self.root, padding="3 3 12 12")
self.mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
# Creates button that runs 'handle_input_change'-method on click
ttk.Button(self.mainframe, text="Show graph",
command=self.handle_input_change).grid(column=3, row=4, sticky=E)
The method that runs when the button is clicked
def handle_input_change(self, *args):
# Starts another thread running the 'plot_current_data'-method
thread = Thread(target = self.plot_current_data)
thread.start()
def plot_current_data(self):
fig = # ... (irrelevant, could be any matplotlib figure)
# This is what makes the application crash and output the warning message
canvas = FigureCanvasTkAgg(fig, master=self.mainframe)
canvas.draw()
canvas.get_tk_widget().grid(column=1, row=5, rowspan=10, sticky=W)
When i run it all in the same thread, the code above does display the figure.