Editable table in Matplotlib: How to superimpose a TextBox widget on a table cell?

后端 未结 2 2036
北海茫月
北海茫月 2021-01-24 07:18

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

2条回答
  •  生来不讨喜
    2021-01-24 08:00

    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()
    

提交回复
热议问题