2

I have developed a fairly complex GUI tool using the Qt Designer.

For more details about the tool see: https://github.com/3fon3fonov/trifon

I have defined many QDoubleSpinBox entries and by default the Qt Designer sets their right-click menu policy to:

setContextMenuPolicy(QtCore.Qt.DefaultContextMenu)

Now I want to add few more actions to this menu, but I simply cannot understand how this works! There is nothing in the Qt Designer which will allow me to make a "CustomContextMenu". I understand that for this I may need some coding (with which I will need help, and thus I am asking for help here), but I also need to make it globally for all SpinBox-es.

Sorry for not posting the code since it is fairly large for this form. If interested, please look at the github under "gui.py". However, there and in the .ui file there is no sign of any possibility to control the contextmenu policy for these buttons. Instead I am posting an image of the tool (sorry for the bad image but PrtSc does not seem to work when the right button in clicked and the menu is displayed)

see GUI image here

1 Answers1

1

As we want to add a QAction to the default context menu we first overwrite the contextMenuEvent event and use a QTimer to call a function that filters the toplevels and get the QMenu that is displayed and there we add the QAction:

doublespinbox.py

from PyQt5 import QtCore, QtWidgets

class DoubleSpinBox(QtWidgets.QDoubleSpinBox):
    minimize_signal = QtCore.pyqtSignal()

    def __init__(self, *args, **kwargs):
        super(DoubleSpinBox, self).__init__(*args, **kwargs)
        self.setContextMenuPolicy(QtCore.Qt.DefaultContextMenu)

    def contextMenuEvent(self, event):
        QtCore.QTimer.singleShot(0, self.add_actions)
        super(DoubleSpinBox, self).contextMenuEvent(event)

    @QtCore.pyqtSlot()
    def add_actions(self):
        for w in QtWidgets.QApplication.topLevelWidgets():
            if isinstance(w, QtWidgets.QMenu) and w.objectName() == "qt_edit_menu":
                w.addSeparator()
                minimize_action = w.addAction("minimize this parameter")
                minimize_action.triggered.connect(self.minimize_signal)

if __name__ == '__main__':
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = DoubleSpinBox()
    w.show()
    sys.exit(app.exec_())

To use DoubleSpinBox in Qt Designer, first place doublespinbox.py next to your .ui:

├── ..
├── rvmod_gui.ui
├── doublespinbox.py   
├── ...

then you must promote the widget to do so right click on the QDoubleSpinBox and select the option "Promote to ..." by adding the following to the dialog:

enter image description here

Then click on the Add button and then the Promote button.

For the other QDoubleSpinBox, right click and select the new Promote To option where the DoubleSpinBox option is.


You can find an example here

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • Dear eyllanesc, It looks very accurate! Unfortunately, it still does not work. Let me first ask an additional question... in the rvmod_gui.ui I see that the designer-qt5 have assigned QDoubleSpinBox not DoubleSpinBox. Do you think it should be the first, e.g. class QDoubleSpinBox(QtWidgets.QDoubleSpinBox):...? but even then I still dont get the "minimize this parameter" in the context menu. – Trifon Trifonov Nov 27 '18 at 20:52
  • I just checked it is PyQt5.QtWidgets.QDoubleSpinBox – Trifon Trifonov Nov 27 '18 at 21:08
  • @TrifonTrifonov The solution is not as simple as you point, I am implementing it now – eyllanesc Nov 27 '18 at 21:11
  • @TrifonTrifonov What is the main file of your project? – eyllanesc Nov 27 '18 at 21:15
  • gui.py; this file loads many libraries to operate including the "rvmod_gui.ui", which I created with the designer-qt5. Thanks for helping! – Trifon Trifonov Nov 27 '18 at 21:34
  • @TrifonTrifonov I have added the method to use in QtDesigner, the solution is to promote as you use with PlotWidget. On the other hand I have improved the DoubleSpinBox code. And finally I added a link where there is an example. – eyllanesc Nov 27 '18 at 22:13
  • @TrifonTrifonov If my answer helps you do not forget to mark it as correct, if you do not know how to do it then review the [tour], that is the best way to thank. – eyllanesc Nov 27 '18 at 22:15
  • WOW! I would never have guessed, although in a similar way I had promoted the pyqtgraph widgets! Thanks a lot, I can confirm it works! I just have to promote all the QDoubleSpinBox, no problem. However, I still need help :) Now how to connect self.minimize_signal with some of my functions in gui.py? I also will need to get some sort of indication which exactly QDoubleSpinBox I have triggered the right button (therefore, minimize this parameter). I dont have these functions build yet but lets assume I want to call "self.optimize_fit()" from gui.py. Many thanks! – Trifon Trifonov Nov 27 '18 at 22:31
  • @TrifonTrifonov In the link that I added at the end of my answer there is an updated example of how to use that signal and get the spinbox: https://github.com/eyllanesc/stackoverflow/blob/master/questions/53496605/main.py – eyllanesc Nov 27 '18 at 22:34