0

I have an unusual case of needing to pass an extra argument when defining a connection to a customContextMenuRequested slot in PyQt.

Of course, the basic command is usually done in the form of:

myListWidget.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
myListWidget.customContextMenuRequested.connect( self.Whatever_Popup )

I'm also aware and often use both the lambda and functools.partial methods to pass extra arguments to other general functions. However, I have a case where I need to pass a QObject (listWidget in this case) when defining the connection.

The receiving function is structured like so:

def Whatever_Popup(self, pos):
    globalPos = self.mapToGlobal(pos)
    globalPos.setX( globalPos.x() + 720)
    globalPos.setY( globalPos.y() + 115)

    menu = QtGui.QMenu()
    menu.addAction("Edit")

    selectedItem = menu.exec_(globalPos)

    if selectedItem:
        if selectedItem.text() == "Edit":
            print "Here"
            #self.DoEdit(widget)

I've tried all the following but with no joy.

myListWidget.customContextMenuRequested.connect( partial(self.Whatever_Popup, newLst))

myListWidget.customContextMenuRequested.connect( partial(self.Whatever_Popup, QtCore.QPoint, newLst))

myListWidget.customContextMenuRequested.connect( partial(self.Whatever_Popup, QtCore.SIGNAL("customContextMenuRequested(const QPoint &)"), newLst))

myListWidget.customContextMenuRequested.connect( lambda: self.Whatever_Popup, (QtCore.SIGNAL("customContextMenuRequested(const QPoint &)"), newLst) )

All return an error. Am I close? or is this perhaps not possible? which would be a bit surprising.

myListWidget is generated dynamically btw. I need to pass some reference to the listWidget because self.DoEdit(widget) will need it for further processing. Can't pre-define the name and retrieve it in self.DoEdit since it's created dynamically. Does anyone have a solution to this? Thanks to all in advance,

clemtoy
  • 1,681
  • 2
  • 18
  • 30
Coleslaw
  • 31
  • 1
  • 4
  • ahh..this is related, testing now...http://stackoverflow.com/questions/22856614/passing-argument-to-pyqt-signal-connection – Coleslaw Jul 31 '15 at 21:57
  • Why `partial` doesn't work? – cdonts Jul 31 '15 at 22:00
  • lol, wish I knew ;-) Doing a myListWidget.customContextMenuRequested.connect( partial(self.Whatever_Popup, QtCore.SIGNAL("customContextMenuRequested(const QPoint &)"), myListWidget)) returns TypeError: QWidget.mapToGlobal(QPoint): argument 1 has unexpected type 'str' – Coleslaw Jul 31 '15 at 22:10
  • You don't need to put the second argument, it will be passed automatically by Qt. Just `partial(self.Whatever_Popup, myListWidget)`. – cdonts Jul 31 '15 at 22:15
  • btw,..why does this "add comment" area not respect carriage return? – Coleslaw Jul 31 '15 at 22:15
  • right, sorry,..I did a version without "pos" and it too errors – Coleslaw Jul 31 '15 at 22:16
  • `myListWidget.customContextMenuRequested.connect( partial( self.Whatever_Popup, myListWidget) )` returns `TypeError: QWidget.mapToGlobal(QPoint): argument 1 has unexpected type 'QListWidget'` – Coleslaw Jul 31 '15 at 22:21
  • Just like this: `myListWidget.customContextMenuRequested.connect(partial(self.Whatever_Popup, new_argument))` – cdonts Jul 31 '15 at 22:21
  • just to clarify, the receiving function is defined as def Whatever_Popup(self, pos, widget): – Coleslaw Jul 31 '15 at 22:23
  • apologies, cdonts,..please see my edited comment just before yours... – Coleslaw Jul 31 '15 at 22:23

2 Answers2

1

Here you have a working example:

from functools import partial

from PyQt4.QtCore import Qt, QObject
from PyQt4.QtGui import QApplication, QMainWindow, QListWidget


class MainWindow(QMainWindow):

    def __init__(self):
        QMainWindow.__init__(self)

        self.resize(800, 600)
        self.list_widget = QListWidget(self)
        self.list_widget.setContextMenuPolicy(Qt.CustomContextMenu)
        my_object = QObject()
        self.list_widget.customContextMenuRequested.connect(
            partial(self.receiver, my_object))

        self.setCentralWidget(self.list_widget)

    def receiver(self, my_object, pos):
        pass


if __name__ == "__main__":
    app = QApplication([])
    window = MainWindow()
    window.show()
    app.exec_()

Replace my_object with whatever you need.

Hope it helps.

cdonts
  • 9,304
  • 4
  • 46
  • 72
0

I stumbled on the answer,...have to rearrange the receiving functions arguments like so:

before:

def Whatever_Popup(self, pos, widget):

after:

def Whatever_Popup(self, widget, pos):
Coleslaw
  • 31
  • 1
  • 4