""" Demonstrates adding a custom context menu to a GraphicsItem and extending the context menu of a ViewBox. PyQtGraph implements a system that allows each item in a scene to implement its own context menu, and for the menus of its parent items to be automatically displayed as well. """ import pyqtgraph as pg from pyqtgraph.Qt import QtCore, QtGui, QtWidgets win = pg.GraphicsLayoutWidget(show=True) win.setWindowTitle('pyqtgraph example: context menu') view = win.addViewBox() # add two new actions to the ViewBox context menu: zoom1 = view.menu.addAction('Zoom to box 1') zoom2 = view.menu.addAction('Zoom to box 2') # define callbacks for these actions def zoomTo1(): # note that box1 is defined below view.autoRange(items=[box1]) zoom1.triggered.connect(zoomTo1) def zoomTo2(): # note that box1 is defined below view.autoRange(items=[box2]) zoom2.triggered.connect(zoomTo2) class MenuBox(pg.GraphicsObject): """ This class draws a rectangular area. Right-clicking inside the area will raise a custom context menu which also includes the context menus of its parents. """ def __init__(self, name): self.name = name self.pen = pg.mkPen('r') # menu creation is deferred because it is expensive and often # the user will never see the menu anyway. self.menu = None # note that the use of super() is often avoided because Qt does not # allow to inherit from multiple QObject subclasses. pg.GraphicsObject.__init__(self) # All graphics items must have paint() and boundingRect() defined. def boundingRect(self): return QtCore.QRectF(0, 0, 10, 10) def paint(self, p, *args): p.setPen(self.pen) p.drawRect(self.boundingRect()) # On right-click, raise the context menu def mouseClickEvent(self, ev): if ev.button() == QtCore.Qt.MouseButton.RightButton: if self.raiseContextMenu(ev): ev.accept() def raiseContextMenu(self, ev): menu = self.getContextMenus() # Let the scene add on to the end of our context menu # (this is optional) menu = self.scene().addParentContextMenus(self, menu, ev) pos = ev.screenPos() menu.popup(QtCore.QPoint(int(pos.x()), int(pos.y()))) return True # This method will be called when this item's _children_ want to raise # a context menu that includes their parents' menus. def getContextMenus(self, event=None): if self.menu is None: self.menu = QtWidgets.QMenu() self.menu.setTitle(self.name+ " options..") green = QtGui.QAction("Turn green", self.menu) green.triggered.connect(self.setGreen) self.menu.addAction(green) self.menu.green = green blue = QtGui.QAction("Turn blue", self.menu) blue.triggered.connect(self.setBlue) self.menu.addAction(blue) self.menu.green = blue alpha = QtWidgets.QWidgetAction(self.menu) alphaSlider = QtWidgets.QSlider() alphaSlider.setOrientation(QtCore.Qt.Orientation.Horizontal) alphaSlider.setMaximum(255) alphaSlider.setValue(255) alphaSlider.valueChanged.connect(self.setAlpha) alpha.setDefaultWidget(alphaSlider) self.menu.addAction(alpha) self.menu.alpha = alpha self.menu.alphaSlider = alphaSlider return self.menu # Define context menu callbacks def setGreen(self): self.pen = pg.mkPen('g') # inform Qt that this item must be redrawn. self.update() def setBlue(self): self.pen = pg.mkPen('b') self.update() def setAlpha(self, a): self.setOpacity(a/255.) # This box's context menu will include the ViewBox's menu box1 = MenuBox("Menu Box #1") view.addItem(box1) # This box's context menu will include both the ViewBox's menu and box1's menu box2 = MenuBox("Menu Box #2") box2.setParentItem(box1) box2.setPos(5, 5) box2.setScale(0.2) if __name__ == '__main__': pg.exec()