Search code examples
pythonpyqtpyqt5pyqtgraph

ScaleBar in pyqtgraph won't setParentItem


I'm trying to set a scale bar in an ImageView in pyqtgraph / PyQt5 but when I setParentItem for the scale bar it won't accept the ImageView, ImageItem or ViewBox. There is no error message but the whole program crashes.

from PyQt5 import QtGui
import pyqtgraph as pg
import numpy as np

app = QtGui.QApplication([])

imvOCTTopLeft = pg.ImageView(view=pg.PlotItem())
imvOCTTopLeft.setImage(np.random.normal(size=(100,100)))
scale = pg.ScaleBar(size=0.1)
im=imvOCTTopLeft.getImageItem()
scale.setParentItem(im)

imvOCTTopLeft.show()

app.exec_()

Solution

  • I recommend you execute your code in a CMD or Terminal so you can get more information about the error, if you do you will get the following message:

    Traceback (most recent call last):
      File "/usr/lib/python3.7/site-packages/pyqtgraph/graphicsItems/GraphicsObject.py", line 23, in itemChange
        self.parentChanged()
      File "/usr/lib/python3.7/site-packages/pyqtgraph/graphicsItems/ScaleBar.py", line 44, in parentChanged
        view.sigRangeChanged.connect(self.updateBar)
    AttributeError: 'ImageItem' object has no attribute 'sigRangeChanged'
    Aborted (core dumped)
    

    And that error is caused because setParentItem() method requires a ViewBox since it has sigRangeChanged signal that allows to update the ScaleBar if there is some type of zoom. Then you can get the ViewBox through the view attribute, but if you pass a parameter in the constructor using view as you have done (pg.ImageView(view = pg.PlotItem())) then you must get the viewbox through of that object using getViewBox().

    Another error in your code is that QApplication belongs to the QtWidgets submodule of PyQt5.

    from PyQt5 import QtWidgets
    import pyqtgraph as pg
    import numpy as np
    
    if __name__ == '__main__':
        import sys
    
        app = QtWidgets.QApplication(sys.argv)
    
        imvOCTTopLeft = pg.ImageView(view=pg.PlotItem())
        imvOCTTopLeft.setImage(np.random.normal(size=(100,100)))
        scale = pg.ScaleBar(size=10)
        viewbox = imvOCTTopLeft.view
        if not isinstance(viewbox, pg.ViewBox): viewbox = viewbox.getViewBox()
        scale.setParentItem(viewbox)
        scale.anchor((1, 1), (1, 1), offset=(-200, -20))
        imvOCTTopLeft.show()
    
        sys.exit(app.exec_())