How to pass arguments to callback functions in PyQt

后端 未结 5 1485
臣服心动
臣服心动 2020-11-30 10:21

I have around 10 QAction (this number will vary in runtime) in a toolbar, which all will do same thing, but using different parameters. I am thinking to add parameter as an

相关标签:
5条回答
  • 2020-11-30 10:51

    There is still a bug in the way PyQt uses QSignalMapper. I discovered a work-around here:

    http://www.riverbankcomputing.com/pipermail/pyqt/2010-March/026113.html

    To fix the answered question make the following change:

            action.triggered[()].connect(self.mapper.map)
    

    This was needed for the following version of Python:

    Python 2.6.6 (r266:84292, Feb 21 2013, 19:26:11)
    [GCC 4.4.7 20120313 (Red Hat 4.4.7-3)] on linux2
    
    0 讨论(0)
  • 2020-11-30 10:56

    You can send the action object itself using a signal mapper. However, it may be better to simply send an identifier and do all the work within the signal handler.

    Here's a simple demo script:

    from PyQt4 import QtGui, QtCore
    
    class Window(QtGui.QMainWindow):
        def __init__(self):
            QtGui.QMainWindow.__init__(self)
            self.mapper = QtCore.QSignalMapper(self)
            self.toolbar = self.addToolBar('Foo')
            self.toolbar.setToolButtonStyle(QtCore.Qt.ToolButtonTextOnly)
            for text in 'One Two Three'.split():
                action = QtGui.QAction(text, self)
                self.mapper.setMapping(action, text)
                action.triggered.connect(self.mapper.map)
                self.toolbar.addAction(action)
            self.mapper.mapped['QString'].connect(self.handleButton)
            self.edit = QtGui.QLineEdit(self)
            self.setCentralWidget(self.edit)
    
        def handleButton(self, identifier):
            if identifier == 'One':
                text = 'Do This'
            elif identifier == 'Two':
                text = 'Do That'
            elif identifier == 'Three':
                text = 'Do Other'
            self.edit.setText(text)
    
    if __name__ == '__main__':
    
        import sys
        app = QtGui.QApplication(sys.argv)
        window = Window()
        window.resize(300, 60)
        window.show()
        sys.exit(app.exec_())
    
    0 讨论(0)
  • 2020-11-30 11:07

    You could use a lambda function associated to the GUI control's slot to pass extra arguments to the method you want to execute.

    # Create the build button with its caption
    self.build_button = QPushButton('&Build Greeting', self)
    # Connect the button's clicked signal to AddControl
    self.build_button.clicked.connect(lambda: self.AddControl('fooData'))
    def AddControl(self, name):
        print name
    

    Source: snip2code - Using Lambda Function To Pass Extra Argument in PyQt4

    0 讨论(0)
  • 2020-11-30 11:17

    How to pass arguments to callback functions in PyQt

    You can use functools.partial from standart Python library. Example with QAction:

    some_action.triggered.connect(functools.partial(some_callback, param1, param2))
    
    0 讨论(0)
  • 2020-11-30 11:18

    The best way to pass the arguments is to not pass them at all. You can use the dynamic nature of python, and set whatever data you need as your own properties on the widgets themselves, get the target widget in the handler using self.sender(), and then get whatever properties you need directly from the widget.

    In this example five buttons are created and the required state is set on the button widget as my_own_data property:

    import sys
    from PyQt4 import QtGui, QtCore
    
    class Main(QtGui.QMainWindow):
    
        def __init__(self):
            QtGui.QMainWindow.__init__(self)
            self.centralwidget = QtGui.QWidget()
            self.vboxlayout = QtGui.QVBoxLayout()
    
            for idx in range(5):
                button = QtGui.QPushButton('button ' + str(idx), None)
                button.my_own_data = str(idx)  # <<< set your own property
                button.clicked.connect(self.click_handler)  # <<< no args needed
                self.vboxlayout.addWidget(button)
    
            self.centralwidget.setLayout(self.vboxlayout)
            self.setCentralWidget(self.centralwidget)
            self.show()
    
        def click_handler(self, data=None):
            if not data:
                target = self.sender()  # <<< get the event target, i.e. the button widget
                data = target.my_own_data  # <<< get your own property
            QtGui.QMessageBox.information(self, 
                                          "you clicked me!", 
                                          "my index is {0}".format(data))
    
    app = QtGui.QApplication(sys.argv)
    main = Main()
    main.show()
    
    sys.exit(app.exec_())
    
    0 讨论(0)
提交回复
热议问题