I have been struggling with getting my matplotlib graph embedded in tkinter GUI; I could have used QTPython which looks really neat but it was too late.
This is my following code for updating graphs in tkinter GUI (it is embedded, no external window) I would like to resize the chart to fit correctly. I have so far tried the following:
1) Tight Layout : fig_findin.tight_layout() 2) Yticks Wrap True 3) I have tried different bar width from 0.1 to 0.6
My main problem is to reduce the height of the Gray background frame (the grid lines frame or subplot). this would make the title completely visible and it would look consistent with the other graph. I would also like the y_axis labels to be wrapped but still visible in the existing frame.
Here is my code for the matplotlib graphs.
def animate_artifact_graph(i):
#######################################
''' GRAPH START '''
#######################################
## DATA
x_cat = [x[1] for x in db.query_artifact()]
x_cat = x_cat[:-2]
y_count = {}
for i in x_cat:
y_count[i] = 0
artifact_name,proj_name,mod_name = artifact_type_select.get() ,proj_select.get(),proj_mod_select.get()
if(artifact_name == 'All'):
artifact_name = db.query_artifact_name()
else:
artifact_name = [artifact_name]
observations_fr_project = db.query_closed_findings_by_project(proj_name,mod_name,artifact_name)
title = proj_name + " - " + mod_name
for i in observations_fr_project:
y_count[i[2]] = y_count[i[2]] + 1
y_count = { k:v for k, v in y_count.items() if v > 0 and k != 'RTM'}
x = list(y_count.keys())
y = list(y_count.values())
# ## SHOW
# rects = ax.patches
# labels = [ i for i in list(y_count.values())]
# for rect, label in zip(rects, labels):
# if(rect.get_height() > 0):
# height = rect.get_height() - 1.50
# width = rect.get_width() /2
# ax.text(rect.get_x() + width, rect.get_y()+height-0.26,label)
# ax.set_ylabel("Observations", fontsize=12)
# ax.set_xlabel("Artifact Type", fontsize=12)
ax.clear()
now = datetime.datetime.now()
date_display = now.strftime('%A, %d %B %Y, %H:%M')
ax.set_title (title + "\n" + "Total number of findings per deliverable type\n(as of " + date_display + ")", fontsize=8)
def func(pct, allvals):
absolute = int(pct/100.*np.sum(allvals))
return "{:.1f}%\n{:d}".format(pct, absolute)
wedges, texts, autotexts = ax.pie(y, autopct=lambda pct: func(pct, y),
textprops=dict(color="w"))
ax.legend(wedges, x,
title="Artifact Types",
loc="center left",
bbox_to_anchor=(1, 0, 0.5, 1))
fig_artif.tight_layout()
ax.axis('equal') # Equal aspect ratio ensures that pie is drawn as a circle.
#######################################
''' GRAPH END '''
#######################################
def animate_finding_graph(i):
#######################################
''' GRAPH START '''
#######################################
## DATA
x_cat = [x[1] for x in db.query_finding()]
y_count = {}
for i in x_cat:
y_count[i] = 0
artifact_name,proj_name,mod_name = artifact_type_select.get() ,proj_select.get(),proj_mod_select.get()
if(artifact_name == 'All'):
artifact_name = db.query_artifact_name()
else:
artifact_name = [artifact_name]
observations_fr_project = db.query_closed_findings_by_project(proj_name,mod_name,artifact_name)
title = proj_name + " - " + mod_name
for i in observations_fr_project:
y_count[i[1]] = y_count[i[1]] + 1
y_count = { k:v for k, v in y_count.items() if v > 0 and k != 'nan'}
y_count = OrderedDict(sorted(y_count.items(), key=lambda kv: kv[1],reverse=True))
if(len(list(y_count.keys())) >= 5):
to_remove = list(y_count.keys())[5:]
for x in to_remove:
del y_count[x]
x = list(y_count.values())
y = list(y_count.keys())
## SHOW
ay.clear()
bar_width = 0.4
ay.barh(y,x,bar_width,align='edge',color='yellow')
ay.invert_yaxis()
rects = ay.patches
# print("rects",len(rects))
labels = [ i for i in list(y_count.values())]
# print("\n")
for rect, label in zip(rects, labels):
height = rect.get_height()/2
width = rect.get_width() - 0.50
ay.text(rect.get_x() + width, rect.get_y()+height,label,fontsize=8)
ay.tick_params(
axis='x', # changes apply to the x-axis
which='both', # both major and minor ticks are affected
bottom=False, # ticks along the bottom edge are off
top=False, # ticks along the top edge are off
labelbottom=False) # labels along the bottom edge are off
ay.set_yticklabels(y,fontsize=6,wrap=True)
for tick in ay.yaxis.get_major_ticks():
tick.label1.set_verticalalignment('center')
now = datetime.datetime.now()
date_display = now.strftime('%A, %d %B %Y, %H:%M')
ay.set_title (title + "\n" + "Top 5 Deliverables.", fontsize=6)
#######################################
## ''' GRAPH END '''
#######################################
def artifact_graph():
canvas_artifact = FigureCanvasTkAgg(fig_artif, master=tab1_closed_observations)
canvas_artifact.get_tk_widget().grid(row=7,column=0,padx=10,pady=5,columnspan=3)
ani = animation.FuncAnimation(fig_artif, animate_artifact_graph,interval=500)
canvas_artifact.draw()
def export_win():
output_folder = "./Reports/" + proj_select.get() + " -- " + proj_mod_select.get()
if not os.path.exists(output_folder):
os.makedirs(output_folder)
fig_artif.savefig(output_folder + "/artifact.png")
export_artifact_graph = Button(tab1_closed_observations, text='Export', command=export_win)
export_artifact_graph.grid(row=6,column=0,padx=70,pady=20,sticky='we',columnspan=2)
def finding_category():
canvas_finding = FigureCanvasTkAgg(fig_findin, master=tab1_closed_observations)
canvas_finding.get_tk_widget().grid(row=7,column=5,padx=10,pady=5,columnspan=3)
ani = animation.FuncAnimation(fig_findin, animate_finding_graph,interval=500)
canvas_finding.draw()
def export_win():
output_folder = "./Reports/"+ proj_select.get() + " -- " + proj_mod_select.get()
if not os.path.exists(output_folder):
os.makedirs(output_folder)
fig_findin.savefig(output_folder + "/finding.png")
export_finding_graph = Button(tab1_closed_observations, text='Export', command=export_win)
export_finding_graph.grid(row=6,column=5,padx=70,pady=20,sticky='we',columnspan=3)
This is how my graphs look :
i figured out how to have a snug fit but still could not make the yticks appear neatly.
The catch is to decrease bar width and hide all other y axes accessories. Adding Wrap = True and vertical aligning the labels make it look pretty.
bar_width = 0.4
ay.barh(y,x,bar_width,color='yellow')
ay.tick_params(
axis='x', # changes apply to the x-axis
which='both', # both major and minor ticks are affected
bottom=False, # ticks along the bottom edge are off
top=False, # ticks along the top edge are off
labelbottom=False
)
ay.set_yticklabels(y,fontsize=6,wrap=True)
for tick in ay.yaxis.get_major_ticks():
tick.label1.set_verticalalignment('center')
This is how it looks now :
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.