I\'m progressing towards creating an interactive table in Matplotlib. I want the user to be able to click on a data cell in the table so they can edit its value. Based on the ad
Using @ImportanceOfBeingErnest's very helpful answer I was able to adapt my original code to a working solution. Yes, I know it uses horrible globals, etc but at least it works!
import matplotlib.pyplot as plt
from matplotlib.table import CustomCell
from matplotlib.widgets import TextBox
def on_pick(event):
if isinstance(event.artist, CustomCell):
global text_box, current_cell, table
if text_box is not None:
plt.gcf().delaxes(text_box.ax)
current_cell = event.artist
table_axes = table.axes
axes_to_display = table_axes.transAxes
display_to_figure = table_axes.figure.transFigure.inverted()
bbox = current_cell.get_bbox().transformed(axes_to_display + display_to_figure)
text_box_axes = plt.axes(bbox.bounds)
cell_text = current_cell.get_text().get_text()
text_box = TextBox(text_box_axes, '', initial=cell_text)
text_box.on_submit(update_table_cell)
plt.draw()
def update_table_cell(new_value):
global text_box, current_cell
# Get rid of the textbox:
plt.gcf().delaxes(text_box.ax)
current_cell.get_text().set_text(new_value)
text_box = None
current_cell = None
# TODO: Update the table data...
plt.draw()
column_labels = ('Length', 'Width', 'Height', 'Sold?')
row_labels = ['Ferrari', 'Porsche']
data = [[2.2, 1.6, 1.2, True],
[2.1, 1.5, 1.4, False]]
table = plt.table(cellText=data, colLabels=column_labels, rowLabels=row_labels, cellLoc='center', loc='bottom')
text_box = None
current_cell = None
celld = table.get_celld()
for key in celld.keys():
# Each key is a tuple of the form (row, column).
# Column headings are in row 0. Row headings are in column -1.
# So the first item of data in the table is actually at (1, 0).
if key[0] > 0 and key[1] > -1:
cell = celld[key]
cell.set_picker(True)
canvas = plt.gcf().canvas
canvas.mpl_connect('pick_event', on_pick)
plt.axis('off')
plt.show()