Display Pandas and Matplotlib Charts in Tkinter

Pandas pie chart displayed inside a Tkinter window using Matplotlib

This tutorial shows how to display Pandas plots and Matplotlib charts inside a Tkinter application. We begin with a simple DataFrame, embed a pie chart in Tkinter, display multiple charts, and then create a dynamic chart using records from a MySQL or SQLite database.

Matplotlib provides FigureCanvasTkAgg, which places a Matplotlib Figure inside a Tkinter widget.

Pandas DataFrame
      |
      v
Matplotlib Figure
      |
      v
FigureCanvasTkAgg
      |
      v
Tkinter window

Required Libraries Top ↑

The main libraries are Pandas, Matplotlib and Tkinter.

import tkinter as tk
from tkinter import ttk

import pandas as pd

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure

Figure creates the Matplotlib chart container. FigureCanvasTkAgg connects that Figure to Tkinter.

Display a Pandas Pie Chart in Tkinter Top ↑

Create a Pandas DataFrame:

data={
    'NAME':[
        'Infant',
        'Child',
        'Young',
        'Old'
    ],
    'Nos':[
        30,
        40,
        50,
        50
    ]
}

df=pd.DataFrame(data)

Create a Matplotlib Figure and Axes:

fig=Figure(
    figsize=(4,4),
    dpi=100
)

ax=fig.add_subplot(
    111
)

Pandas can draw directly on that Axes:

df.plot.pie(
    y='Nos',
    labels=df['NAME'],
    title='Population',
    legend=False,
    ax=ax
)

Complete Pie Chart Example Top ↑

import tkinter as tk
import pandas as pd

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure

data={'NAME':['Infant','Child','Young','Old'],
      'Nos':[30,40,50,50]}

df=pd.DataFrame(data)

root=tk.Tk()
root.title('Pandas Pie Chart - plus2net')

fig=Figure(figsize=(4,4),dpi=100)
ax=fig.add_subplot(111)

df.plot.pie(
    y='Nos',
    labels=df['NAME'],
    title='Population',
    legend=False,
    ax=ax
)

canvas=FigureCanvasTkAgg(fig,master=root)
canvas.draw()
canvas.get_tk_widget().pack(
    fill=tk.BOTH,
    expand=True
)

root.mainloop()

How FigureCanvasTkAgg Works Top ↑

A Matplotlib Figure is not automatically a Tkinter widget.

The bridge is:

canvas=FigureCanvasTkAgg(
    fig,
    master=root
)

Draw the Figure:

canvas.draw()

Then obtain the Tkinter widget:

canvas.get_tk_widget()

This widget can use normal Tkinter layout methods such as grid() or pack().

Display Multiple Plots in the Same Tkinter Window Top ↑

Pie chart and line chart displayed together in one Tkinter window

Create separate Figures when two independent charts are needed.

import tkinter as tk
import pandas as pd

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure

root=tk.Tk()
root.title('Multiple Charts - plus2net')

population=pd.DataFrame({
    'NAME':['Infant','Child','Young','Old'],
    'Nos':[30,40,50,50]
})

marks=pd.DataFrame({
    'NAME':['Ravi','Raju','Alex','Ron','Geek','Kim'],
    'MARK':[20,30,40,30,40,50]
})

fig1=Figure(figsize=(4,3),dpi=100)
ax1=fig1.add_subplot(111)
population.plot.pie(
    y='Nos',
    labels=population['NAME'],
    legend=False,
    ax=ax1
)

fig2=Figure(figsize=(4,3),dpi=100)
ax2=fig2.add_subplot(111)
marks.plot(
    x='NAME',
    y='MARK',
    marker='o',
    legend=False,
    ax=ax2
)

canvas1=FigureCanvasTkAgg(fig1,master=root)
canvas1.draw()
canvas1.get_tk_widget().grid(row=0,column=0)

canvas2=FigureCanvasTkAgg(fig2,master=root)
canvas2.draw()
canvas2.get_tk_widget().grid(row=1,column=0)

root.mainloop()

Create Dynamic Charts from MySQL or SQLite Top ↑

Dynamic Tkinter Matplotlib chart created from database records

The next example reads student records from MySQL or SQLite. A Combobox contains the available class names. When the user selects a class, Pandas loads the names and marks for that class and the existing chart is redrawn.

The sample table structure is the same student table used in several Plus2net database tutorials.

Load Distinct Class Names for the Combobox Top ↑

Create the SQLAlchemy Engine:

engine=create_engine(
    'sqlite:///my_db.db'
)

For MySQL:

engine=create_engine(
    'mysql+mysqldb://root:password@localhost/my_tutorial'
)

Use a SQLAlchemy 2.x connection to read the distinct class values:

class_sql=text(
    'SELECT DISTINCT class '
    'FROM student '
    'WHERE class IS NOT NULL '
    'ORDER BY class'
)

with engine.connect() as conn:
    result=conn.execute(
        class_sql
    )

    class_list=[
        row[0]
        for row in result
    ]

This replaces the older:

engine.execute(query)

pattern.

Use a Parameterized Query for the Selected Class Top ↑

The old code constructed SQL like this:

query="SELECT name,mark FROM student WHERE class='"+sel.get()+"'"

Application values should not be joined directly into SQL text.

Use a parameter:

student_sql=text(
    'SELECT name,mark '
    'FROM student '
    'WHERE class=:class_name '
    'ORDER BY name'
)

Then pass the selected value separately:

with engine.connect() as conn:
    df=pd.read_sql(
        student_sql,
        conn,
        params={
            'class_name':selected_class
        }
    )

See Pandas read_sql() with database records and SQLAlchemy database connections for related examples.

Update the Graph when Combobox Selection Changes Top ↑

The older example tracked a StringVar using:

sel.trace(
    'w',
    my_upd
)

Because the interaction comes from a Combobox, the more direct event is:

class_combo.bind(
    '<<ComboboxSelected>>',
    update_plot
)

The Combobox is also set to:

state='readonly'

so the user selects only one of the database values.

Reuse One Matplotlib Canvas Top ↑

The old my_upd() function created another Figure and another FigureCanvasTkAgg every time the class changed.

Repeated selections could therefore create multiple overlapping chart widgets.

The revised application creates these once:

fig=Figure(...)
ax=fig.add_subplot(111)

canvas=FigureCanvasTkAgg(
    fig,
    master=chart_frame
)

For each update:

ax.clear()

then draw the new DataFrame:

ax.plot(
    df['name'],
    df['mark'],
    marker='o'
)

Finally:

canvas.draw_idle()

The same Tkinter canvas now displays the updated chart.

Complete Dynamic Database Chart Application Top ↑

The following example uses SQLite by default. Change DATABASE_URL to the MySQL connection string when using the same student table in MySQL.

Use MySQL Instead of SQLite Top ↑

The application logic does not need to change. Replace:

DATABASE_URL='sqlite:///my_db.db'

with the required MySQL SQLAlchemy URL:

DATABASE_URL=(
    'mysql+mysqldb://'
    'root:password@localhost/my_tutorial'
)

The same parameterized queries and Pandas DataFrame plotting logic can then be used.

Download Sample SQLite Database Student Table SQL Dump

Video: Pandas Database Graphs inside Tkinter Top ↑

Plotting graphs in Tkinter generated from Pandas DataFrame using MySQL or SQLite data

Why Parameterized SQL Matters Top ↑

The old approach:

"WHERE class='"+selected_class+"'"

mixes application values with the SQL statement.

The revised approach keeps them separate:

SQL:
WHERE class=:class_name

Parameters:
{
    'class_name':selected_class
}

This is clearer, handles values correctly and avoids constructing SQL by concatenating user-controlled text.

Why the Figure Is Created Only Once Top ↑

The chart has three separate objects:

Figure
   |
   v
Axes
   |
   v
FigureCanvasTkAgg

Changing the selected class does not require creating these objects again.

Only the plotted data changes:

Combobox change
      |
      v
query database
      |
      v
new DataFrame
      |
      v
ax.clear()
      |
      v
draw new values
      |
      v
canvas.draw_idle()

This prevents new chart widgets from accumulating in the window.

Pie Chart from Database Records Top ↑

The same dynamic application can display a pie chart instead of a line chart.

After loading plot_df, replace the line plotting section with:

ax.pie(
    plot_df['mark'],
    labels=plot_df['name'],
    autopct='%1.0f%%'
)

ax.set_title(
    f'Marks - Class {selected_class}'
)

Whether a pie chart is meaningful depends on the data being represented. For comparing student marks, a line or bar chart is often easier to compare precisely.

Continue the Tkinter Data Projects Top ↑

Build more Pandas DataFrame applications:

Tkinter Pandas Projects

Analyze CSV records with GroupBy and Pivot Tables:

Pandas Data Analysis

Search DataFrame rows through Tkinter:

Search DataFrame

Display database records in Treeview:

MySQL Records in Treeview

Frequently Asked Questions Top ↑

Q1: How do I display a Matplotlib chart inside Tkinter?

Create a Matplotlib Figure and pass it to FigureCanvasTkAgg. The canvas provides a Tkinter widget that can be placed with grid() or pack().

Q2: Can Pandas plot directly on a Matplotlib Axes?

Yes. Pandas plotting methods accept the ax parameter, allowing the DataFrame plot to use an Axes created for the Tkinter application.

Q3: Why should the Matplotlib canvas be reused?

Creating another canvas after every user selection can produce overlapping widgets and unnecessary Figure objects. Clearing and redrawing the existing Axes is more efficient.

Q4: How can a Combobox update a chart?

Bind <<ComboboxSelected>> to a function that loads the selected data, clears the Axes, plots the new records and calls canvas.draw_idle().

Q5: Why use a parameterized SQL query?

Parameterized SQL keeps application values separate from the SQL statement and avoids constructing database queries by joining user-controlled strings.

Q6: Can the same program work with MySQL and SQLite?

Yes. SQLAlchemy provides Engines for both databases. The plotting and Tkinter code can remain the same when the table structure and SQL query are compatible.

Q7: What happens when the selected database query returns no rows?

The application clears the existing chart, displays a message on the Figure or status Label, and waits for another Combobox selection.


Pandas Analysis Tkinter Pandas Projects

Resize Images with PIL Upload and Display Images Create QR Code


Subscribe to our YouTube Channel here



plus2net.com







Python Video Tutorials
Python SQLite Video Tutorials
Python MySQL Video Tutorials
Python Tkinter Video Tutorials
We use cookies to improve your browsing experience. . Learn more
HTML MySQL PHP JavaScript ASP Photoshop Articles Contact us
©2000-2026   plus2net.com   All rights reserved worldwide Privacy Policy Disclaimer