Redefining the Context Menu on right click

4,462 views
Skip to first unread message

Morgan Cherioux

unread,
Jul 3, 2014, 7:10:35 AM7/3/14
to pyqt...@googlegroups.com
Hello everyone,
I'm currently using pyqtgraph and for the need of my program I need to remove some options from the contextMenu and add some of mine.
I already found how to remove the "Plot Options" and "Export" tools with the following code ( self is a PlotWidget subclass here ) :

        self.plotItem.ctrlMenu = None  # get rid of 'Plot Options'
       
self..scene().contextMenu = None  # get rid of 'Export'

Indeed, for the need of my program I'm subclassing a PlotWidget to work with a CustomViewBox (which inherit from ViewBox with some new tools that I implemented). 
What I would like to do is removing the "X axis" and "Y axis" tools, rename "View All" and "Mouse Mode" while keeping their current behavior and then add some tools myself to this menu.
If someone has any thoughts on how to do that, please let me know. 
For more details here is my PlotWidget subclass briefly : 

class PltWidget(pg.PlotWidget):
   
"""
    Subclass of PlotWidget
    """



   
def __init__(self, parent=None):
       
"""
        Constructor of the widget
        """

       
super(PltWidget, self).__init__(parent, viewBox=CustomViewBox())
       
self.plotItem.showGrid(True, True, 0.7) # Show grid
       
self.plotItem.setLabel('left', units='mV') # Show label
       
self.plotItem.ctrlMenu = None  # get rid of 'Plot Options'
       
self.scene().contextMenu = None  # get rid of 'Export'

Thanks,
Morgan.

Morgan Cherioux

unread,
Jul 3, 2014, 11:33:01 AM7/3/14
to pyqt...@googlegroups.com
I find an efficient way of doing it thanks to this link : http://nullege.com/codes/show/src%40b%40m%40BMDanalyse-0.1.3%40BMDanalyse%40ViewBoxCustom.py/19/pyqtgraph.ViewBox/python
I hope it can help people wondering about this ;)

I don't know if it is very optimal but as I'm already subclassing ViewBox for other tools, it fits perfectly my program.
You can find the result here, re-using "View All" and "Mouse Mode" tools as well as adding my own actions.

class CustomViewBox(pg.ViewBox):
   
"""
    Subclass of ViewBox
    """

    signalShowT0
= QtCore.Signal()
    signalShowS0
= QtCore.Signal()

   
def __init__(self, parent=None):
       
"""
        Constructor of the CustomViewBox
        """

       
super(CustomViewBox, self).__init__(parent)
       
self.setRectMode() # Set mouse mode to rect for convenient zooming
       
self.menu = None # Override pyqtgraph ViewBoxMenu
       
self.menu = self.getMenu() # Create the menu

   
def raiseContextMenu(self, ev):
       
"""
        Raise the context menu
        """

       
if not self.menuEnabled():
           
return
        menu
= self.getMenu()
        pos  
= ev.screenPos()
        menu
.popup(QtCore.QPoint(pos.x(), pos.y()))

   
def getMenu(self):
       
"""
        Create the menu
        """

       
if self.menu is None:
           
self.menu = QtGui.QMenu()
           
self.viewAll = QtGui.QAction("Vue d\'ensemble", self.menu)
           
self.viewAll.triggered.connect(self.autoRange)
           
self.menu.addAction(self.viewAll)
           
self.leftMenu = QtGui.QMenu("Mode clic gauche")
           
group = QtGui.QActionGroup(self)
            pan
= QtGui.QAction(u'Déplacer', self.leftMenu)
            zoom
= QtGui.QAction(u'Zoomer', self.leftMenu)
           
self.leftMenu.addAction(pan)
           
self.leftMenu.addAction(zoom)
            pan
.triggered.connect(self.setPanMode)
            zoom
.triggered.connect(self.setRectMode)
            pan
.setCheckable(True)
            zoom
.setCheckable(True)
            pan
.setActionGroup(group)
            zoom
.setActionGroup(group)
           
self.menu.addMenu(self.leftMenu)
           
self.menu.addSeparator()
           
self.showT0 = QtGui.QAction(u'Afficher les marqueurs d\'amplitude', self.menu)
           
self.showT0.triggered.connect(self.emitShowT0)
           
self.showT0.setCheckable(True)
           
self.showT0.setEnabled(False)
           
self.menu.addAction(self.showT0)
           
self.showS0 = QtGui.QAction(u'Afficher les marqueurs de Zone d\'intégration', self.menu)
           
self.showS0.setCheckable(True)
           
self.showS0.triggered.connect(self.emitShowS0)
           
self.showS0.setEnabled(False)
           
self.menu.addAction(self.showS0)
       
return self.menu

   
def emitShowT0(self):
       
"""
        Emit signalShowT0
        """

       
self.signalShowT0.emit()

   
def emitShowS0(self):
       
"""
        Emit signalShowS0
        """

       
self.signalShowS0.emit()

   
def setRectMode(self):
       
"""
        Set mouse mode to rect
        """

       
self.setMouseMode(self.RectMode)

   
def setPanMode(self):
       
"""
        Set mouse mode to pan
        """

       
self.setMouseMode(self.PanMode)

I'm kind of new to python and Qt/Pyside so it may not be the best implementation for it but it's working ;) 
Please let me know if you find something that can improve the way I do it.

Luke Campagnola

unread,
Jul 6, 2014, 10:36:13 AM7/6/14
to pyqt...@googlegroups.com
Looks like a good solution to me!


--
You received this message because you are subscribed to the Google Groups "pyqtgraph" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyqtgraph+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pyqtgraph/08954226-1119-47c3-9fcb-21e64c5755e9%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Vincent Le Saux

unread,
Jul 7, 2014, 5:49:55 PM7/7/14
to pyqt...@googlegroups.com
Thanks for the tip. I wanted to do something similar cause I also have some specific needs. For the moment, I have just copied your file and create a PlotWidget into a QMainWindow giving as ViewBox one CustomViewBox instance and I get the following error message : 

 self.menu.setViewList(nv)
AttributeError: 'QMenu' object has no attribute 'setViewList'

Morgan, stupid question may be but how did you manage to get things working? self.menu is by default a ViewBoxMenu instance, roughly a QMenu with some additional methods (and more specifically a setViewList method). With your solution, your self.menu is just a QMenu. Am I missing something?

Regards,

vls 

Morgan Cherioux

unread,
Jul 11, 2014, 8:34:52 AM7/11/14
to pyqt...@googlegroups.com
I should of precised the following. 
After subclassing my ViewBox, I also subclass a PlotWidget which is initialized with this CustomViewBox

class PltWidget(pg.PlotWidget):
    """
    Subclass of PlotWidget
    """
    def __init__(self, parent=None):
        """
        Constructor of the widget
        """
        super(PltWidget, self).__init__(parent, viewBox=CustomViewBox())


Then I use this class to instantiate a PltWidget as I want. I don't know if it will help but that's the best i can provide, the rest of the code is working for me =S

Vincent Le Saux

unread,
Jul 15, 2014, 9:24:24 AM7/15/14
to pyqt...@googlegroups.com
Oups, sorry Morgan, I did not respond to you.

Thank you very much for your response. Everything is clear now!

Thanks again.

Regards,

vls
Reply all
Reply to author
Forward
0 new messages