I would like to display the value of a particular element of a heatmap when I hover the mouse over it.
I have got it to display the value of the heatmap but it displayed information I do not want as well and when I first run the program, there are a lot of errors and I cannot figure out why.
I have tried various methods of displaying the value that I have seen online, such as datacursor(hover=True)
but mplcursors.cursor(hover=True)
is the only one that 'works'.
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
import numpy as np
from math import pi
import random
import matplotlib.pyplot as plt
from mpldatacursor import datacursor
import mplcursors
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import pandas as pd
from openpyxl import load_workbook
from tkinter import filedialog
root = tk.Tk()
root.title("Stage 2 GUI")
root.geometry("1270x590")
mapArr = np.zeros([2,2],dtype=float)
mapArr=([113,62,31,63],
[50,101,72,47],
[92,10,40,12],
[83,21,128,16])
xy=(['A','B','C','D','E','F'])
figure, axis = plt.subplots(figsize=(8,7))
heatmap = axis.imshow(
mapArr,cmap="gray",interpolation='nearest',vmin=0, vmax=128)
heatmap.axes.get_xaxis().set_visible(False)
heatmap.axes.get_yaxis().set_visible(False)
cb = figure.colorbar(heatmap)
canvas = FigureCanvasTkAgg(figure, root)
canvas.get_tk_widget().place(x=-60,y=-60)
mplcursors.cursor(hover=True)
plt.show()
I would like to display the value of the heatmap element but not the x and y coordinates but I am not sure how to remove/ customise the information displayed and I would like it if there were not errors whenever I run the program (even if it technically does work).
You need to decide if you want to use pyplot or embedd matplotlib into tk. The following assumes you want to embedd (in that case, don't use pyplot!!).
The mplcursors documentation explains how to customize the output. Essentially it consists of connecting to an event called "add"
.
import numpy as np
import matplotlib
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import tkinter as tk
import mplcursors
root = tk.Tk()
root.geometry("1270x590")
mapArr=np.array(([113,62,31,63],
[50,101,72,47],
[92,10,40,12],
[83,21,128,16]))
xy=(['A','B','C','D','E','F'])
fig = matplotlib.figure.Figure()
ax = fig.add_subplot()
heatmap = ax.imshow(mapArr,cmap="gray",interpolation='nearest',vmin=0, vmax=128)
cb = fig.colorbar(heatmap)
canvas = FigureCanvasTkAgg(fig, root)
canvas.get_tk_widget().place(x=60,y=60)
cursor = mplcursors.cursor(heatmap, hover=True)
@cursor.connect("add")
def on_add(sel):
i,j = sel.target.index
sel.annotation.set_text(mapArr[i,j])
tk.mainloop()
You can do the same as above without the use of mplcursors. This would be done by creating an annotation and changing its position and text depending on the mouse position.
import numpy as np
import matplotlib
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import tkinter as tk
root = tk.Tk()
root.geometry("1270x590")
mapArr=np.array(([113,62,31,63],
[50,101,72,47],
[92,10,40,12],
[83,21,128,16]))
xy=(['A','B','C','D','E','F'])
fig = matplotlib.figure.Figure()
ax = fig.add_subplot()
heatmap = ax.imshow(mapArr,cmap="gray",interpolation='nearest',vmin=0, vmax=128)
cb = fig.colorbar(heatmap)
canvas = FigureCanvasTkAgg(fig, root)
canvas.get_tk_widget().place(x=60,y=60)
annot = ax.annotate("", xy=(0,0), xytext=(20,20), textcoords="offset points",
arrowprops=dict(arrowstyle="->"), visible=False,
bbox=dict(boxstyle="round", fc="w"))
def hover(event):
if event.inaxes == ax:
x,y = event.xdata, event.ydata
j,i = np.round(np.array((x,y))).astype(int)
annot.xy = (x,y)
annot.set_text(str(mapArr[i,j]))
annot.set_visible(True)
else:
annot.set_visible(False)
fig.canvas.draw_idle()
canvas.mpl_connect("motion_notify_event", hover)
tk.mainloop()