Search code examples
python-3.xqtnonetypepyqtgraph

PyQtGraph SpotItem returns 'NoneType' when calling user data


I am trying to get the associated user data of a point (which is a SpotItem instance) in a scatter plot when clicked on it. While methods listed in the documentation (like pos() or size()) seem to work fine, I recieve a NoneType object when I apply the data() method. I actually expected it to return my user data, but it doesn't.

So, how can I retrieve my associated original data that I put in? What I actually need is something like an index i of the original input lists for a clicked point that would allow me to track back the corresponding x[i] y[i] set.

Here is my code sample:

import pyqtgraph as pg

#some dummy data
x=[0,1,2,3,4,5,3.5,3.4]
y=[5,4,3,2,1,0,3.4,3.5]

win=pg.GraphicsWindow()
p1=win.addPlot(row=1, col=1)
my_data=pg.ScatterPlotItem(x,y,symbol='o',size=30)

p1.addItem(my_data)

def clicked(items,points):
    print("point data: ",points[0].data())


my_data.sigClicked.connect(clicked)

I am using Python 3.6 (with Spyder 3.1.4), Qt 5.6 and PyQt 5


Solution

  • sigClicked gave us the item (ScatterPlotItem) that has been pressed and the points (SpotItem) where they have been pressed, with the seconds we can obtain the element Point() that gives us the position, and this has the methods x() y y() that return the coordinates. From item we can get all the x and y that you have initially placed through data['x'] and data['y'], respectively, then we have the points pressed and all the points possible so to find the indexes we use np.argwhere() and then we intersect the values with np.intersect1d(), at the end we eliminate the repeated points with set.

    import numpy as np
    from pyqtgraph.Qt import QtGui, QtCore
    import pyqtgraph as pg
    
    
    app = QtGui.QApplication([])
    
    x=[0,1,2,3,4,5,3.5,3.4, 3.4]
    y=[5,4,3,2,1,0,3.4,3.5, 3.5]
    
    win=pg.GraphicsWindow()
    p1=win.addPlot(row=1, col=1)
    
    my_data=pg.ScatterPlotItem(x,y,symbol='o',size=30)
    
    p1.addItem(my_data)
    
    def clicked(item, points):
        indexes = []
        for p in points:
            p = p.pos()
            x, y = p.x(), p.y()
            lx = np.argwhere(item.data['x'] == x)
            ly = np.argwhere(item.data['y'] == y)
            i = np.intersect1d(lx, ly).tolist()
            indexes += i
        indexes = list(set(indexes))
        print(indexes)
    
    my_data.sigClicked.connect(clicked)
    
    if __name__ == '__main__':
        import sys
        if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
            QtGui.QApplication.instance().exec_()