Search code examples
python-3.xtkinterpie-chartmatplotlib-widget

Why does my pie chart in Tkinter does not show?


I am building an application which takes input, saves it to a CSV file and now the last basic part is to display a pie chart of the content of the column. The input is supposed to be about books. So, the pie chart should for example display the genre of all the books in the list.

I do not have a problem with creating the pie chart, I managed it in a separate script, I do not receive an error message either but instead have only a white field.

import csv
import tkinter as tk
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from tkinter import ttk
from collections import Counter

class FrontFrames:

    def __init__(self, master):
        super().__init__()
    #Split the screen horizontally in two parts
        top_frame = tk.Frame(master, bg="green")
        bottom_frame = tk.Frame(master, bg="yellow")
        top_frame.pack(side="top", fill="both", expand=True)
        bottom_frame.pack(side="top", fill="both", expand=True)

    #Creating the three top widgets
        self.tree = Label(top_frame)

        column = ("Title", "author", "year", "others")

        self.treeview = ttk.Treeview(top_frame, columns=column, show='headings')
        self.treeview.heading("Title", text="Title")
        self.treeview.heading("author", text="Author")
        self.treeview.heading("year", text="Year")
        self.treeview.heading("others", text="Others")
        content = "./Note.csv"
        with open(content, 'r') as file:
            csv_reader = csv.DictReader(file, skipinitialspace=True)
            for row in csv_reader:
                self.treeview.insert('', '0', values=(f'{row["title"]}',
                                                      f'{row["author"]}',
                                                      f'{row["year"]}',
                                                      f'{row["others"]}'))
                c = Counter(row["others"])

        header = list(c.keys())
        values = list(c.values())
        colors = ['r', 'g', 'b', 'c', 'y']
        f = plt.Figure(figsize=(4,4))
        #a = f.add_subplot(111)
        pie = plt.pie(values, labels=header, colors=colors, startangle=90, 
                      autopct='%.1f%%')
        self.canvas = FigureCanvasTkAgg(f, top_frame)

        self.tree.pack(side="left", fill="both", expand=True)
        self.treeview.pack(side="left", fill="both", expand=True)
        self.canvas.get_tk_widget().pack(side="right", fill="both")
        #self.canvas.show()

I commented out the line "self.canvas.show()" because I otherwise receive the error message:

AttributeError: 'FigureCanvasTkAgg' object has no attribute 'show'

It is always told that the command must be included in order to actually display the pie chart but in a separate test where no other widget are build, the pie chart is visible. I assume that the pie chart is just hidden under another widget.

The content of the CSV would look like the following:

title, author, year, others, note
Everything,Nobody,2222,Fiction,This is just something of everything!
Nothing,Everybody,1111,Romance,This is nothing of anything!
Pokemon,Pikachu,1999,Fiction,Once upon time.
Lord of the rings, R.R. Jackson, 1972, Fantasy, A long story!
Harry Potter, Rowling, 1995, Fantasy, A detailed story.
Bible, Apostels, 0, Fiction, A story.
The Ring, Frank, 1980, Horror, A scary story.
1984, Orwell, 1932, Dystopia, A scary future for the past and scary present 
for us.
Pirates of the Caribbean, Brandow, 1955, Fiction, A pirate story.

I use Python 3.7.0

As always, thank you very much for your helpful answers.


Solution

  • As for self.canvas.show, my python interpreter tells me that FigureCanvasTkAgg.show is deprecated and that I should use draw instead.

    As for the issue with the plot, I managed to make the pie chart appear by uncommenting a = f.add_subplot(111) and by replacing

    plt.pie(values, labels=header, colors=colors, startangle=90, autopct='%.1f%%')
    

    by

    a.pie(values, labels=header, colors=colors, startangle=90, autopct='%.1f%%') 
    

    So my guess is that your chart was displayed in the wrong figure since you weren't explicitly specifying the axes.