I am new to the python and tkinter, I want to create Dashboard using tkinter. I wrote the below code to add the graphs in tkinter using the Matplotlib. As I have 4 graphs and not able to fit all, so added a horizontal scroll bar but somehow it is not working. Please find the below code.
import tkinter as tk
from tkinter import ttk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib.pyplot as plt
import numpy as np
def calculate_gap(sum_of_demand, allocated, capacity):
if sum_of_demand - allocated < 0:
sum_of_not_demanded = abs(sum_of_demand - allocated)
elif capacity - sum_of_demand > 0:
sum_of_not_demanded = capacity - sum_of_demand
else:
sum_of_not_demanded = 0
if capacity - allocated > 0:
spare_capacity = capacity - allocated
else:
spare_capacity = 0
if sum_of_demand - capacity > 0:
skill_gap = sum_of_demand - capacity
else:
skill_gap = 0
return sum_of_not_demanded, spare_capacity, skill_gap
def h_scroll(*args):
print("In scroll")
graph1_canvas.get_tk_widget().xview(*args)
graph2_canvas.get_tk_widget().xview(*args)
graph3_canvas.get_tk_widget().xview(*args)
graph4_canvas.get_tk_widget().xview(*args)
def test_gap():
sum_of_demand = 256
allocated = 73
capacity = 66
sum_of_not_demanded, spare_capacity, skill_gap = calculate_gap(sum_of_demand, allocated, capacity)
width = 0.35
below = np.array([sum_of_demand, allocated, capacity])
above = np.array([sum_of_not_demanded, spare_capacity, skill_gap])
weight_counts = {
"Below": np.array([sum_of_demand, allocated, capacity]),
"Above": np.array([sum_of_not_demanded, spare_capacity, skill_gap])
}
title = ['Demand', 'Allocated', 'Capacity']
bottom = np.zeros(3)
for boolean, weight_count in weight_counts.items():
p = graph4_ax.bar(title, weight_count, width, label=boolean, bottom=bottom)
bottom += weight_count
graph4_canvas.draw()
# canvas1.get_tk_widget().pack(side="left",fill="both",expand=True)
graph4_canvas.get_tk_widget().pack(fill="both", expand=True, side="left")
graph4_canvas.get_tk_widget().config(scrollregion=graph4_canvas.get_tk_widget().bbox("all"))
graph4_canvas.get_tk_widget().config(xscrollcommand=horizontal_scrollbar.set,
scrollregion=graph4_canvas.get_tk_widget().bbox("all"))
# test_canvas.get_tk_widget().config(xscrollcommand=horizontal_scrollbar.set)
# test_canvas.get_tk_widget().bind("<<Key>>", pop_up)
def graph_three():
sum_of_demand = 256
allocated = 73
capacity = 66
sum_of_not_demanded, spare_capacity, skill_gap = calculate_gap(sum_of_demand, allocated, capacity)
if sum_of_demand - capacity > 0:
skill_gap = sum_of_demand - capacity
else:
skill_gap = 0
width = 0.1
weight_counts = {
"Below": np.array([sum_of_demand, allocated, capacity]),
"Above": np.array([sum_of_not_demanded, spare_capacity, skill_gap])
}
title = ['Demand', 'Allocated', 'Capacity']
bottom = np.zeros(3)
for boolean, weight_count in weight_counts.items():
p = graph_ax.bar(title, weight_count, width, label=boolean, bottom=bottom)
bottom += weight_count
graph3_canvas.draw()
# canvas1.get_tk_widget().pack(side="left",fill="both",expand=True)
graph3_canvas.get_tk_widget().pack(fill="both", expand=True, side="left")
graph3_canvas.get_tk_widget().config(scrollregion=graph3_canvas.get_tk_widget().bbox("all"))
graph3_canvas.get_tk_widget().config(xscrollcommand=horizontal_scrollbar.set,
scrollregion=graph3_canvas.get_tk_widget().bbox("all"))
# mobile_canvas.get_tk_widget().config(xscrollcommand=horizontal_scrollbar.set)
def graph_two():
sum_of_demand = 830
allocated = 313
capacity = 339
sum_of_not_demanded, spare_capacity, skill_gap = calculate_gap(sum_of_demand, allocated, capacity)
width = 0.35
weight_counts = {
"Below": np.array([sum_of_demand, allocated, capacity]),
"Above": np.array([sum_of_not_demanded, spare_capacity, skill_gap])
}
title = ['Demand', 'Allocated', 'Capacity']
bottom = np.zeros(3)
for boolean, weight_count in weight_counts.items():
p = graph2_ax.bar(title, width, label=boolean, bottom=bottom)
bottom += weight_count
graph2_canvas.draw()
# canvas1.get_tk_widget().pack(side="left",fill="both",expand=True)
graph2_canvas.get_tk_widget().pack(fill="both", expand=True, side="left")
graph2_canvas.get_tk_widget().config(scrollregion=graph2_canvas.get_tk_widget().bbox("all"))
graph2_canvas.get_tk_widget().config(xscrollcommand=horizontal_scrollbar.set,
scrollregion=graph2_canvas.get_tk_widget().bbox("all"))
# be_canvas.get_tk_widget().config(xscrollcommand=horizontal_scrollbar.set)
def graph_one():
sum_of_demand = 1631
allocated = 778
capacity = 795
sum_of_not_demanded, spare_capacity, skill_gap = calculate_gap(sum_of_demand, allocated, capacity)
width = 0.35
weight_counts = {
"Below": np.array([sum_of_demand, allocated, capacity]),
"Above": np.array([sum_of_not_demanded, spare_capacity, skill_gap])
}
title = ['Demand', 'Allocated', 'Capacity']
bottom = np.zeros(3)
for boolean, weight_count in weight_counts.items():
p = graph1_ax.bar(title, weight_count, width, label=boolean, bottom=bottom)
bottom += weight_count
graph1_canvas.draw()
graph1_canvas.get_tk_widget().config(scrollregion=graph1_canvas.get_tk_widget().bbox("all"))
graph1_canvas.get_tk_widget().config(xscrollcommand=horizontal_scrollbar.set,
scrollregion=graph1_canvas.get_tk_widget().bbox("all"))
# horizontal_scrollbar.config(command=h_scroll())
root = tk.Tk()
# Main Frame
frame = ttk.Frame(root)
frame.pack()
# Data Frame
graph_frame = ttk.Labelframe(frame, text="Skill Gap")
graph_frame.grid(side = tk.RIGHT, expand = True, fill = tk.BOTH)
horizontal_scrollbar = ttk.Scrollbar(graph_frame, orient=tk.HORIZONTAL, command=h_scroll)
horizontal_scrollbar.pack(side=tk.BOTTOM, fill=tk.X)
# Canvas
graph1_fig, graph1_ax = plt.subplots(dpi=100)
graph1_canvas = FigureCanvasTkAgg(graph1_fig, graph_frame)
horizontal_scrollbar.config(command=graph1_canvas.get_tk_widget().xview)
graph1_canvas.get_tk_widget().config(yscrollcommand=horizontal_scrollbar.set)
# Canvas
graph2_fig, graph2_ax = plt.subplots(dpi=100)
graph2_canvas = FigureCanvasTkAgg(graph2_fig, graph_frame)
# Canvas
graph3_fig, graph_ax = plt.subplots(dpi=100)
graph3_canvas = FigureCanvasTkAgg(graph3_fig, graph_frame)
# Canvas
graph4_fig, graph4_ax = plt.subplots(dpi=100)
graph4_canvas = FigureCanvasTkAgg(graph4_fig, graph_frame)
graph_one()
graph_two()
graph_three()
test_gap()
horizontal_scrollbar.config(command=h_scroll)
tk.mainloop()
I am expecting horizontal scroll bar to be work. And able to scroll though all the graphs.
Tkitner
can scroll only Canvas
, Listbox
and Text
but not Frame
If you want to scroll all elements then you have to put them in one tkinter.Frame
and this frame put on tkinter.Canvas
and use tkinter.Scrollbar
to scroll this frame on canvas.
I took one of my code from answer to your previous question
python - Not able to show more than 4-5 bar charts using matplotlib - Stack Overflow
and I added scrolled cavnas
import tkinter as tk
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
# --- functions ---
def resize(event):
dashboard_canvas.configure(scrollregion=dashboard_canvas.bbox('all'))
# --- main ---
x = [1, 2, 3, 4]
y = [1, 2, 3, 4]
AS = [10 / 2 ** 0]
# ---
root = tk.Tk()
root.geometry("1000x1000")
root.title("eggs")
# ---
# canvas
dashboard_canvas = tk.Canvas(root)#, bg='#00c000') # background color only to test its size
dashboard_inner_frame = tk.Frame(dashboard_canvas)
inner_frame_id = dashboard_canvas.create_window((0,0), window=dashboard_inner_frame, anchor='nw')
dashboard_canvas.pack(fill='both', expand=True)
# scrollbar
dasboard_scrollbar_x = tk.Scrollbar(root, orient='horizontal')
dasboard_scrollbar_x.pack(fill='x')
# join widgets
dashboard_canvas.configure(xscrollcommand=dasboard_scrollbar_x.set)
dasboard_scrollbar_x['command'] = dashboard_canvas.xview
# resize scrollregion on canvas when plots will have size (and it will be after starting program and drawing plots)
dashboard_inner_frame.bind('<Configure>', resize)
#---
# put on dashboard_inner_frame
frame_top = tk.Frame(dashboard_inner_frame, width=2000)
frame_top.pack(fill='both', expand=True)
plots = []
for index in range(10):
fig = Figure(dpi=100)
ax = fig.add_subplot(111)
ax.plot(x, y)
fig.suptitle(f"Plot {index+1}")
canvas = FigureCanvasTkAgg(fig, master=frame_top)
canvas.draw()
canvas.get_tk_widget().pack(side="left", fill='both', expand=True)
#canvas.get_tk_widget()['width'] = 1
plots.append({'fig': fig, 'canvas': canvas})
root.mainloop()
Version with code from current question
import tkinter as tk
from tkinter import ttk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib.pyplot as plt
import numpy as np
# --- functions ---
def resize(event):
dashboard_canvas.configure(scrollregion=dashboard_canvas.bbox('all'))
def calculate_gap(sum_of_demand, allocated, capacity):
if sum_of_demand - allocated < 0:
sum_of_not_demanded = abs(sum_of_demand - allocated)
elif capacity - sum_of_demand > 0:
sum_of_not_demanded = capacity - sum_of_demand
else:
sum_of_not_demanded = 0
if capacity - allocated > 0:
spare_capacity = capacity - allocated
else:
spare_capacity = 0
if sum_of_demand - capacity > 0:
skill_gap = sum_of_demand - capacity
else:
skill_gap = 0
return sum_of_not_demanded, spare_capacity, skill_gap
def h_scroll(*args):
print("In scroll")
graph1_canvas.get_tk_widget().xview(*args)
graph2_canvas.get_tk_widget().xview(*args)
graph3_canvas.get_tk_widget().xview(*args)
graph4_canvas.get_tk_widget().xview(*args)
def test_gap():
sum_of_demand = 256
allocated = 73
capacity = 66
sum_of_not_demanded, spare_capacity, skill_gap = calculate_gap(sum_of_demand, allocated, capacity)
width = 0.35
below = np.array([sum_of_demand, allocated, capacity])
above = np.array([sum_of_not_demanded, spare_capacity, skill_gap])
weight_counts = {
"Below": np.array([sum_of_demand, allocated, capacity]),
"Above": np.array([sum_of_not_demanded, spare_capacity, skill_gap])
}
title = ['Demand', 'Allocated', 'Capacity']
bottom = np.zeros(3)
for boolean, weight_count in weight_counts.items():
p = graph4_ax.bar(title, weight_count, width, label=boolean, bottom=bottom)
bottom += weight_count
graph4_canvas.draw()
# canvas1.get_tk_widget().pack(side="left",fill="both",expand=True)
graph4_canvas.get_tk_widget().pack(fill="both", expand=True, side="left")
graph4_canvas.get_tk_widget().config(scrollregion=graph4_canvas.get_tk_widget().bbox("all"))
# test_canvas.get_tk_widget().config(xscrollcommand=horizontal_scrollbar.set)
# test_canvas.get_tk_widget().bind("<<Key>>", pop_up)
def graph_three():
sum_of_demand = 256
allocated = 73
capacity = 66
sum_of_not_demanded, spare_capacity, skill_gap = calculate_gap(sum_of_demand, allocated, capacity)
if sum_of_demand - capacity > 0:
skill_gap = sum_of_demand - capacity
else:
skill_gap = 0
width = 0.1
weight_counts = {
"Below": np.array([sum_of_demand, allocated, capacity]),
"Above": np.array([sum_of_not_demanded, spare_capacity, skill_gap])
}
title = ['Demand', 'Allocated', 'Capacity']
bottom = np.zeros(3)
for boolean, weight_count in weight_counts.items():
p = graph_ax.bar(title, weight_count, width, label=boolean, bottom=bottom)
bottom += weight_count
graph3_canvas.draw()
# canvas1.get_tk_widget().pack(side="left",fill="both",expand=True)
graph3_canvas.get_tk_widget().pack(fill="both", expand=True, side="left")
graph3_canvas.get_tk_widget().config(scrollregion=graph3_canvas.get_tk_widget().bbox("all"))
# mobile_canvas.get_tk_widget().config(xscrollcommand=horizontal_scrollbar.set)
def graph_two():
sum_of_demand = 830
allocated = 313
capacity = 339
sum_of_not_demanded, spare_capacity, skill_gap = calculate_gap(sum_of_demand, allocated, capacity)
width = 0.35
weight_counts = {
"Below": np.array([sum_of_demand, allocated, capacity]),
"Above": np.array([sum_of_not_demanded, spare_capacity, skill_gap])
}
title = ['Demand', 'Allocated', 'Capacity']
bottom = np.zeros(3)
for boolean, weight_count in weight_counts.items():
p = graph2_ax.bar(title, width, label=boolean, bottom=bottom)
bottom += weight_count
graph2_canvas.draw()
# canvas1.get_tk_widget().pack(side="left",fill="both",expand=True)
graph2_canvas.get_tk_widget().pack(fill="both", expand=True, side="left")
graph2_canvas.get_tk_widget().config(scrollregion=graph2_canvas.get_tk_widget().bbox("all"))
# be_canvas.get_tk_widget().config(xscrollcommand=horizontal_scrollbar.set)
def graph_one():
sum_of_demand = 1631
allocated = 778
capacity = 795
sum_of_not_demanded, spare_capacity, skill_gap = calculate_gap(sum_of_demand, allocated, capacity)
width = 0.35
weight_counts = {
"Below": np.array([sum_of_demand, allocated, capacity]),
"Above": np.array([sum_of_not_demanded, spare_capacity, skill_gap])
}
title = ['Demand', 'Allocated', 'Capacity']
bottom = np.zeros(3)
for boolean, weight_count in weight_counts.items():
p = graph1_ax.bar(title, weight_count, width, label=boolean, bottom=bottom)
bottom += weight_count
graph1_canvas.draw()
graph1_canvas.get_tk_widget().config(scrollregion=graph1_canvas.get_tk_widget().bbox("all"))
# horizontal_scrollbar.config(command=h_scroll())
root = tk.Tk()
# Main Frame
frame = ttk.Frame(root)
frame.pack(expand=True, fill='both')
# Data Frame
graph_frame = ttk.Labelframe(frame, text="Skill Gap")
graph_frame.pack(expand=True, fill='both')
# ---
# canvas
dashboard_canvas = tk.Canvas(graph_frame)#, bg='#00c000') # background color only to test its size
dashboard_inner_frame = tk.Frame(dashboard_canvas)
inner_frame_id = dashboard_canvas.create_window((0,0), window=dashboard_inner_frame, anchor='nw')
dashboard_canvas.pack(fill='both', expand=True)
# scrollbar
dasboard_scrollbar_x = tk.Scrollbar(graph_frame, orient='horizontal')
dasboard_scrollbar_x.pack(fill='x')
# join widgets
dashboard_canvas.configure(xscrollcommand=dasboard_scrollbar_x.set)
dasboard_scrollbar_x['command'] = dashboard_canvas.xview
# resize scrollregion on canvas when plots will have size (and it will be after starting program and drawing plots)
dashboard_inner_frame.bind('<Configure>', resize)
#-----
# Canvas
graph1_fig, graph1_ax = plt.subplots(dpi=100)
graph1_canvas = FigureCanvasTkAgg(graph1_fig, dashboard_inner_frame)
# Canvas
graph2_fig, graph2_ax = plt.subplots(dpi=100)
graph2_canvas = FigureCanvasTkAgg(graph2_fig, dashboard_inner_frame)
# Canvas
graph3_fig, graph_ax = plt.subplots(dpi=100)
graph3_canvas = FigureCanvasTkAgg(graph3_fig, dashboard_inner_frame)
# Canvas
graph4_fig, graph4_ax = plt.subplots(dpi=100)
graph4_canvas = FigureCanvasTkAgg(graph4_fig, dashboard_inner_frame)
graph_one()
graph_two()
graph_three()
test_gap()
tk.mainloop()
I remove your scrollbar and I put all FigureCanvasTkAgg in the same deskboard_inner_frame
and I put deskboard_canvas
and deskboard_scrollbar
in your label_frame
.
To make it more controlled you can keep both desckboard_cavnas
and deskboard_scrollbarin one frame (e.g.
deskboardor
deskboard_outer_frame) and then you have to put only one element in
label_frame`
Code is long and it hard to explain - so maybe use tool like Meld to see differences between your version and my version.