Search code examples
python-3.xmatplotlibtkinterttkbootstrap

How to embed a plot with ttkbootstrap, Tkinter, and Matplotlib?


I found this code online and it's exactly my use case with some modifications. How to Embed Matplotlib charts in tkinter gui

What I have is:

import argparse
import matplotlib.pyplot as plt
from tkinter import *
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)

parser = argparse.ArgumentParser()
parser.add_argument('-x', '--x', type = int)
parser.add_argument('-y', '--y', type = int)
args = parser.parse_args()

# Pass args to variables
x = args.x
y = args.y

class Plot:
    def __init__(self, x, y):
        self.x = x
        self.y = y

fig, ax = plt.subplots(figsize=(5,5))
plt.close(fig)

def plotter(ax):
    axes_name = plt.gca().name
    print(axes_name)

    plt.grid(color = 'k', linestyle = '-', linewidth =1)

    # More plt code for the plot.
    
    canvas = FigureCanvasTkAgg(fig, master = window)
    canvas.draw()

    toolbar = NavigationToolbar2Tk(canvas, window)
    toolbar.update()

    canvas.get_tk_widget().pack=()

window = ttk.Window(themename='superhero')
window.title='Plot of Point'
window.geometry = ('750x750')
plot_button = ttk.Button(master = window, 
                         command = plotter(ax),
                         width = 15,
                         text = 'Create Plot', 
                         bootstyle = 'primary')
window.mainloop()

I'm passing in two values one for x and y to plot a single point on a grid. I was able to figure out I needed a class instead of global variables in order to use those values in my function.

However, I can't seem to get any pylot (plt) attributes set in my function so I tried to pass the axes (ax) and get the name inside the function and that did work. I couldn't get fig inside the function so I thought using ax was the correct object to pass to the function.

When I run the script, the window displays before the Create Plot button is pressed. I don't see the button. Then I get 3 windows displaying, so I'm accidentally creating multiple figures as well. The original code from the link works well enough, but my changes are breaking things.

I believe I have multiple issues, but the main one is to somehow get plt to work. Any ideas as to what I'm doing wrong here?

I added a screenshot of the 3 windows in the GUI. I'm using Python3x and anaconda with Visual Studio Code as the IDE.

enter image description here


Solution

  • You have used = wrong in the following lines:

    ...
    def plotter(ax):
        ...
        canvas.get_tk_widget().pack=()
    ...
    window.title='Plot of Point'
    window.geometry = ('750x750')
    ...
    

    It should be:

    ...
    def plotter(ax):
        ...
        canvas.get_tk_widget().pack()
    ...
    window.title('Plot of Point')
    window.geometry('750x750')
    ...
    

    Also command=plotter(ax) will execute plotter(ax) immediately. Use lambda instead: command=lambda: plotter(ax).

    And you need to call plot_button.pack() to show the button.