0

I learned how to embed a matploblib graph into a Tkinter GUI via this post https://matplotlib.org/examples/user_interfaces/embedding_in_tk.html. It seems working fine.

However, I had a problem with getting multiple matplotlib graphs to work correctly simultaneously, let me explain a bit more here. The code below generates two buttons, each links to a new window with two new buttons (load data and plot data). You may generate some dummy two column data, say data1.txt, data2.txt, data3.txt, data4.txt, for plotting. What I observed is (1) If I invoke the window separately, I have no problem loading and plotting data1.txt, data2.txt, data3.txt, data4.txt. However, if I open the two windows at the same time, I can only plot freely and correctly in the second window, while the first window plots nothing. It seems as if the first window were suppressed by the existence of the second.

Can anyone help me understand what is happening here. My matplotlib version is 2.0.2. Tkinter version is $Revision:81008$. Python version 2.7.15. Thank you!

from Tkinter import *
import Tkinter as tk
import ttk
import tkFileDialog
import numpy
##loading matplotlib modules
import matplotlib
matplotlib.use("TkAgg")
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
import matplotlib.gridspec as gridspec


class Overall_Look:
    def __init__(self, master):
        self.master = master

        self.top_frame = ttk.Frame(self.master, padding = (10, 10))
        self.top_frame.pack()

        ##here are the layout for step 1, load structure files

        ttk.Button(self.top_frame, text = "Button_1", command = self.plot_one,
                   style = "TButton").grid(row = 1, column = 0, columnspan = 2, padx = 5, sticky = "sw")
        ttk.Button(self.top_frame, text = "Button_2",command = self.plot_two,
                   style = "TButton").grid(row = 1, column = 2, columnspan = 2, padx = 5, sticky = "sw")

    def plot_one(self):
        self.plot_one = tk.Toplevel(self.master)
        self.GUI = Plot_One(self.plot_one)

    def plot_two(self):
        self.plot_two = tk.Toplevel(self.master)
        self.GUI = Plot_Two(self.plot_two)


class Plot_One():
    def __init__(self, master):
        self.master = master

        self.top_frame = ttk.Frame(self.master, padding = (10, 10))
        self.top_frame.pack()

        ##here are the layout for step 1, load structure files

        ttk.Button(self.top_frame, text = "Load Data 1", command = self.load_data_1,
                             style = "TButton").grid(row = 1, column = 0, columnspan = 2, padx = 5, sticky = "sw")
        ttk.Button(self.top_frame, text = "Plot Data 1",command = self.start_plot_one,
                             style = "TButton").grid(row = 1, column = 2, columnspan = 2, padx = 5)

        self.bottom_frame = ttk.Frame(self.master, padding = (10, 10))
        self.bottom_frame.pack()

        self.fig_1 = plt.figure(figsize=(5, 5), dpi=100) ##create a figure; modify the size here
        self.fig_1.add_subplot(111)

        self.fig_1.tight_layout()

        self.canvas = FigureCanvasTkAgg(self.fig_1, master = self.bottom_frame)
        self.canvas.show()
        self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
        self.toolbar = NavigationToolbar2TkAgg(self.canvas, self.bottom_frame)
        self.toolbar.update()
        self.canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)


    def load_data_1(self):
        self.data_1 = tkFileDialog.askopenfilename(defaultextension = ".txt",
                                                             filetypes = [("Text Documents", "*.txt")])

    def start_plot_one(self):

        data = numpy.loadtxt(self.data_1).transpose()
        x = data[0]
        y = data[1]

        self.fig_1.clf()
        self.fig_1.add_subplot(111)
        plt.plot(x, y, 'b-', lw=2)
        self.fig_1.tight_layout()
        self.canvas.draw()

class Plot_Two():
    def __init__(self, master):
        self.master = master

        self.top_frame = ttk.Frame(self.master, padding = (10, 10))
        self.top_frame.pack()

        ##here are the layout for step 1, load structure files

        ttk.Button(self.top_frame, text = "Load Data 2", command = self.load_data_2,
                   style = "TButton").grid(row = 1, column = 0, columnspan = 2, padx = 5, sticky = "sw")
        ttk.Button(self.top_frame, text = "Plot Data 2",command = self.start_plot_two,
                  style = "TButton").grid(row = 1, column = 2, columnspan = 2, padx = 5)

        self.bottom_frame = ttk.Frame(self.master, padding = (10, 10))
        self.bottom_frame.pack()

        self.fig_2 = plt.figure(figsize=(5, 5), dpi=100) ##create a figure; modify the size here
        self.fig_2.add_subplot(111)

        self.fig_2.tight_layout()

        self.canvas = FigureCanvasTkAgg(self.fig_2, master = self.bottom_frame)
        self.canvas.show()
        self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
        self.toolbar = NavigationToolbar2TkAgg(self.canvas, self.bottom_frame)
        self.toolbar.update()
        self.canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)


    def load_data_2(self):
        self.data_2 = tkFileDialog.askopenfilename(defaultextension = ".txt",
        filetypes = [("Text Documents", "*.txt")])

    def start_plot_two(self):

        data = numpy.loadtxt(self.data_2).transpose()
        x = data[0]
        y = data[1]

        self.fig_2.clf()
        self.fig_2.add_subplot(111)
        plt.plot(x, y, 'b-', lw=2)
        self.fig_2.tight_layout()
        self.canvas.draw()

def main():
    root = Tk()
    GUI = Overall_Look(root)
    root.mainloop()

if __name__ == "__main__": main()
Chenyang
  • 161
  • 1
  • 11
  • Without looking in detail through the code, I can tell you that you should not be using `pyplot` at all in such cases as this one. Remove the pyplot import and replace all occurences of it with the respective methods of the objects you're dealing with. – ImportanceOfBeingErnest Jun 13 '18 at 22:52
  • Precisely! If I change to an Object-Oriented way of plotting, i.e. using self.ax.plot(x, y), the problem is solved! Thank you for an expert answer! – Chenyang Jun 14 '18 at 00:21

0 Answers0