Reputation: 15
I tried to plot a graph once click on 'home' in the menu bar and display it on the right side of the menu bar in a new frame but in same root. the frame is displayed but the graph doesn't appear. here's my code:
from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.figure import Figure
import pandas as pd
from tkinter import *
from PIL import Image, ImageTk
import matplotlib.pyplot as plt
import matplotlib
matplotlib.use('TkAgg')
root = Tk()
width = root.winfo_screenwidth()
height = root.winfo_screenheight()
# setting tkinter window size
root.geometry("%dx%d" % (width, height))
min_w = 50 # Minimum width of the frame
max_w = 200 # Maximum width of the frame
cur_width = min_w # Increasing width of the frame
expanded = False # Check if it is completely exanded
def Graph():
df = pd.read_csv('nbrePieces.csv', encoding='Utf-8')
# display x: session of the employ, y: number of "OK" pieces producted
x = df['SESSION']
y = df['OK']
fig = Figure(figsize=(12, 10))
ax = fig.add_subplot(111)
ax.bar(x, y, color='g')
ax.set_xlabel('SESSION')
ax.set_ylabel('DATA')
ax.legend()
ax.grid()
canvas = FigureCanvasTkAgg(fig, master=frameG)
canvas.get_tk_widget().grid(rows=0, column=0)
canvas.draw()
def expand():
global cur_width, expanded
cur_width += 10 # Increase the width by 10
rep = root.after(5, expand) # Repeat this func every 5 ms
frame.config(width=cur_width) # Change the width to new increase width
if cur_width >= max_w: # If width is greater than maximum width
expanded = True # Frame is expended
root.after_cancel(rep) # Stop repeating the func
fill()
def fill():
if expanded: # If the frame is exanded
# Show a text, and remove the image
home_b.config(text='Home', image='', font=(0, 15))
liste_b.config(text='liste employés', image='', font=(0, 15))
ajout_b.config(text='ajouter employés', image='', font=(0, 15))
settings_b.config(text='settings', image='', font=(0, 15))
else:
# Bring the image back
home_b.config(image=home, font=(0, 15))
liste_b.config(image=liste, font=(0, 15))
ajout_b.config(image=ajouter, font=(0, 15))
settings_b.config(image=settings, font=(0, 15))
def contract():
global cur_width, expanded
cur_width -= 10 # Reduce the width by 10
rep = root.after(5, contract) # Call this func every 5 ms
frame.config(width=cur_width) # Change the width to new reduced width
if cur_width <= min_w: # If it is back to normal width
expanded = False # Frame is not expanded
root.after_cancel(rep) # Stop repeating the func
fill()
# Define the icons to be shown and resize it
home = ImageTk.PhotoImage(Image.open(
'home.png').resize((40, 40), Image.ANTIALIAS))
liste = ImageTk.PhotoImage(Image.open(
'liste.png').resize((40, 40), Image.ANTIALIAS))
ajouter = ImageTk.PhotoImage(Image.open(
'ajouter.png').resize((40, 40), Image.ANTIALIAS))
settings = ImageTk.PhotoImage(Image.open(
'settings.png').resize((40, 40), Image.ANTIALIAS))
root.update() # For the width to get updated
frame = Frame(root, bg='#C1FFC1', width=50, height=root.winfo_height())
frame.grid(row=0, column=0)
# create the frame where the graph will appear
frameG = Frame(root, bg='gray2', width=1000,
height=root.winfo_height(), padx=3, pady=3)
frameG.grid(row=0, column=1, sticky="nsew")
# Make the buttons with the icons to be shown
home_b = Button(frame, image=home, bg='#C1FFC1',
command=lambda: Graph, relief='flat')
liste_b = Button(frame, image=liste, bg='#C1FFC1', relief='flat')
ajout_b = Button(frame, image=ajouter, bg='#C1FFC1', relief='flat')
settings_b = Button(frame, image=settings, bg='#C1FFC1', relief='flat')
# Put them on the frame
home_b.grid(row=0, column=0, pady=10)
liste_b.grid(row=1, column=0, pady=10)
ajout_b.grid(row=2, column=0, pady=10)
settings_b.grid(row=3, column=0, pady=10)
# Bind to the frame, if entered or left
frame.bind('<Enter>', lambda e: expand())
frame.bind('<Leave>', lambda e: contract())
# So that it does not depend on the widgets inside the frame
frame.grid_propagate(False)
root.mainloop()
i want once i click on the button 'home'in my menu bar a graph will appear in the full right side of my menu bar. thanks in advance
Upvotes: 1
Views: 424
Reputation: 143216
I found two problems
It has to be command=lambda:Graph()
with ()
or command=Graph
without ()
and without lambda
typo in line
canvas.get_tk_widget().grid(row=0, column=0)
it has to be row
instead of rows
After that it works.
Minimal working code.
I use empty images Image.new()
to display it without files.
I put example data directly in code.
This way everyone can simply copy and run it.
from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.figure import Figure
import pandas as pd
from tkinter import *
from PIL import Image, ImageTk
import matplotlib.pyplot as plt
import matplotlib
matplotlib.use('TkAgg')
root = Tk()
width = root.winfo_screenwidth()
height = root.winfo_screenheight()
# setting tkinter window size
root.geometry("%dx%d" % (width, height))
min_w = 50 # Minimum width of the frame
max_w = 200 # Maximum width of the frame
cur_width = min_w # Increasing width of the frame
expanded = False # Check if it is completely exanded
def Graph():
#df = pd.read_csv('nbrePieces.csv', encoding='Utf-8')
df = pd.DataFrame({'SESSION':[1,2,3], 'OK':[10,12,14]})
# display x: session of the employ, y: number of "OK" pieces producted
x = df['SESSION']
y = df['OK']
fig = Figure(figsize=(12, 10))
ax = fig.add_subplot(111)
ax.bar(x, y, color='g')
ax.set_xlabel('SESSION')
ax.set_ylabel('DATA')
ax.legend()
ax.grid()
canvas = FigureCanvasTkAgg(fig, master=frameG)
canvas.get_tk_widget().grid(row=0, column=0) # typo: `row`
canvas.draw()
def expand():
global cur_width, expanded
cur_width += 10 # Increase the width by 10
rep = root.after(5, expand) # Repeat this func every 5 ms
frame.config(width=cur_width) # Change the width to new increase width
if cur_width >= max_w: # If width is greater than maximum width
expanded = True # Frame is expended
root.after_cancel(rep) # Stop repeating the func
fill()
def fill():
if expanded: # If the frame is exanded
# Show a text, and remove the image
home_b.config(text='Home', image='', font=(0, 15))
liste_b.config(text='liste employés', image='', font=(0, 15))
ajout_b.config(text='ajouter employés', image='', font=(0, 15))
settings_b.config(text='settings', image='', font=(0, 15))
else:
# Bring the image back
home_b.config(image=home, font=(0, 15))
liste_b.config(image=liste, font=(0, 15))
ajout_b.config(image=ajouter, font=(0, 15))
settings_b.config(image=settings, font=(0, 15))
def contract():
global cur_width, expanded
cur_width -= 10 # Reduce the width by 10
rep = root.after(5, contract) # Call this func every 5 ms
frame.config(width=cur_width) # Change the width to new reduced width
if cur_width <= min_w: # If it is back to normal width
expanded = False # Frame is not expanded
root.after_cancel(rep) # Stop repeating the func
fill()
# Define the icons to be shown and resize it
#home = ImageTk.PhotoImage(Image.open('home.png').resize((40, 40), Image.ANTIALIAS))
#liste = ImageTk.PhotoImage(Image.open('liste.png').resize((40, 40), Image.ANTIALIAS))
#ajouter = ImageTk.PhotoImage(Image.open('ajouter.png').resize((40, 40), Image.ANTIALIAS))
#settings = ImageTk.PhotoImage(Image.open('settings.png').resize((40, 40), Image.ANTIALIAS))
home = ImageTk.PhotoImage(Image.new('RGB', (40,40), 'red'))
liste = ImageTk.PhotoImage(Image.new('RGB', (40,40), 'green'))
ajouter = ImageTk.PhotoImage(Image.new('RGB', (40,40), 'blue'))
settings = ImageTk.PhotoImage(Image.new('RGB', (40,40), 'yellow'))
root.update() # For the width to get updated
frame = Frame(root, bg='#C1FFC1', width=50, height=root.winfo_height())
frame.grid(row=0, column=0)
# create the frame where the graph will appear
frameG = Frame(root, bg='gray2', width=1000,
height=root.winfo_height(), padx=3, pady=3)
frameG.grid(row=0, column=1, sticky="nsew")
# Make the buttons with the icons to be shown
home_b = Button(frame, image=home, bg='#C1FFC1',
command=lambda: Graph(), relief='flat')
liste_b = Button(frame, image=liste, bg='#C1FFC1', relief='flat')
ajout_b = Button(frame, image=ajouter, bg='#C1FFC1', relief='flat')
settings_b = Button(frame, image=settings, bg='#C1FFC1', relief='flat')
# Put them on the frame
home_b.grid(row=0, column=0, pady=10)
liste_b.grid(row=1, column=0, pady=10)
ajout_b.grid(row=2, column=0, pady=10)
settings_b.grid(row=3, column=0, pady=10)
# Bind to the frame, if entered or left
frame.bind('<Enter>', lambda e: expand())
frame.bind('<Leave>', lambda e: contract())
# So that it does not depend on the widgets inside the frame
frame.grid_propagate(False)
root.mainloop()
Upvotes: 1