pythonpyqtgraph

pyqtgraph: Elegant way to remove a plot from GraphicsLayoutWidget?


I am trying to programmatically add and remove plots to GraphicsLayoutWidget. Adding works as expected via addPlot(row, col) (col is zero for me). Unfortunately there is no removePlot function (which I find odd!), so I am trying to use removeItems(plot). This does not seem to work, though.

Here's a MWE:

import pyqtgraph as pg
import numpy as np

app = pg.mkQApp("MWE")
win = pg.GraphicsLayoutWidget(show=True)

x = np.cos(np.linspace(0, 2*np.pi, 1000))
y = np.sin(np.linspace(0, 4*np.pi, 1000))

plots = []

def add_plot():
    p = win.addPlot(row=len(plots), col=0)
    plots.append(p)
    p.plot(x,y)

def remove_plot(i):
    if 0 <= i <= len(plots)-1:
        p = plots[i]
        win.removeItem(p)
        plots.pop(i)
        p.deleteLater()

add_plot()
add_plot()
add_plot()

remove_plot(1)

add_plot()

pg.exec()

Executing this code leads to QGridLayoutEngine::addItem: Cell (2, 0) already taken. In fact, zooming in or out of the second plot reveals that something is wrong.

I found out that after my attempt at removing a plot win.ci.items and win.ci.rows still have the wrong cell, so I have tried to correct these manually. But, since this did not solve the problem, there must be something else still holding the wrong cells after removing a plot.

  1. What am I missing here?
  2. Is there a counterpart to addPlot? If not, why?
  3. What is an elegant way to remove a plot from GraphicsLayoutWidget?

EDIT: My unsatisfying current workaround is to call win.clear() and add all plots that have not been removed again. Not too elegant.


Solution

  • The (obvious) mistake was on my side: If the function remove_plot is modified as follows, then everything works:

    def remove_plot(i):
        if 0 <= i <= len(plots)-1:
            p = plots[i]
            win.removeItem(p)
            plots.pop(i)
            p.deleteLater()
            
            # defragment 1-d plot grid
            for j in range(i, len(plots)):
                p = plots[j]
                win.removeItem(p)
                win.addItem(p, row=j, col=0)
    

    Maybe this is of help to anyone...