python qt4 - 在QtCore.QObject.connect中传递参数

时间:2013-12-09 14:52:27

标签: python qt4 signals connect slot

我想对QLabel上的鼠标点击做出反应 为此,我重新定义了QLabel的方法mouseReleaseEvent 我想把两个参数传递给插槽:
- QtGui.QMouseEvent
- 单击的QLabel的ID

但我只能传递一个参数。 QtGui.QMouseEvent或ID 这种组合不起作用。

# -*- coding: utf-8 -*-

import sys
from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import pyqtSignal

class ExtendedQLabel(QtGui.QLabel):

    #labelClickSignal_1 = pyqtSignal(QtGui.QMouseEvent)
    labelClickSignal_1 = pyqtSignal(QtGui.QMouseEvent, int)
    labelClickSignal_2 = pyqtSignal()

    def __init(self, parent):
        QtGui.QLabel.__init__(self, parent)

    # redefinition 
    def mouseReleaseEvent(self, event):

        #self.labelClickSignal_1.emit(event)
        self.labelClickSignal_1.emit(event, 0)
        self.labelClickSignal_2.emit()


class Test(QtGui.QMainWindow):

    def __init__(self, parent=None):

        QtGui.QMainWindow.__init__(self, parent)

        self.names = ['Test1', 'Test2', 'Test3']

        self.centralWidget = QtGui.QWidget()
        self.setCentralWidget(self.centralWidget)

        self.grid = QtGui.QGridLayout(self.centralWidget)

        row = 0
        for name in self.names:
            self.addLabel(name, row)
            row = row + 1

    def addLabel(self, name, row):

        label = ExtendedQLabel(name)

        # QtGui.QMouseEvent is automatically passed to the slot
        label.labelClickSignal_1.connect(self.onLabelClicked_1)

        # The row ID is passed to the slot
        label.labelClickSignal_2.connect(lambda id = row: 
                                 self.onLabelClicked_2(id))

        # *This does not work*
        label.labelClickSignal_1.connect(lambda id = row: 
                                 self.onLabelClicked_3(QtGui.QMouseEvent, id))

        self.grid.addWidget(label, row, 1)

        row = row + 1

    def onLabelClicked_1(self, event):

        if event.button() == QtCore.Qt.RightButton:
            print('right')
        else:
            print('left')

    def onLabelClicked_2(self, id):

        print('Label {0} clicked'.format(id))

    def onLabelClicked_3(self, event, id):

        # *This does not work*
        if event.button() == QtCore.Qt.RightButton:
            print('right {0}'.format(id))
        else:
            print('left {0}'.format(id))

def main():        
    app = QtGui.QApplication(sys.argv)

    t = Test()
    t.show()

    sys.exit(app.exec_())

if __name__ == "__main__":
    main()

2 个答案:

答案 0 :(得分:1)

好的,因为你的代码有几件不起作用,我重写了重要的部分来实现你想要的。请注意,我使用PySide而不是PyQt。这意味着您必须将importe语句和Signal更改回PyQt表示法。 其余部分在代码中解释。

import sys
from PySide import QtGui, QtCore

class ExtendedQLabel(QtGui.QLabel):

    #Signal that emits on MouseRelease
    labelClickSignal_1 = QtCore.Signal(QtGui.QMouseEvent, int)

    # init to -1
    labelId = -1

    # This is the new Constructor, Please note the double underscore 
    # before and behind `init`
    def __init__(self, parent, labelId):
        self.labelId = labelId
        QtGui.QLabel.__init__(self, parent)

    # emit labelClickSignal
    def mouseReleaseEvent(self, event):
        self.labelClickSignal_1.emit(event, self.labelId)


class Test(QtGui.QMainWindow):

    def __init__(self, parent=None):

       # same as yours [...]

    def addLabel(self, name, row):

        # please note the added argument
        label = ExtendedQLabel(name,row)

        # connect the signal
        label.labelClickSignal_1.connect(self.onLabelClicked_1)

        self.grid.addWidget(label, row, 1)

        row = row + 1

    def onLabelClicked_1(self, event,labelId):    
        if event.button() == QtCore.Qt.RightButton:
            print('right')
            print(labelId)
        else:
            print('left')
            print(labelId)

OLD ANSWER 您必须定义Signal以支持您的两个参数:

labelClickSignal_1 = pyqtSignal(QtGui.QMouseEvent,int)

有关其他信息,请参阅here

来自文档的示例:

from PyQt4.QtCore import QObject, pyqtSignal

class Foo(QObject):

    # This defines a signal called 'closed' that takes no arguments.
    closed = pyqtSignal()

    # This defines a signal called 'rangeChanged' that takes two
    # integer arguments.
    range_changed = pyqtSignal(int, int, name='rangeChanged')

    # This defines a signal called 'valueChanged' that has two overloads,
    # one that takes an integer argument and one that takes a QString
    # argument.  Note that because we use a string to specify the type of
    # the QString argument then this code will run under Python v2 and v3.
    valueChanged = pyqtSignal([int], ['QString'])

答案 1 :(得分:0)

我想我解决了。注释lambda的{​​{1}}仅使用一个参数,但插槽定义为两个。所以我只是跳过第一个论点。

下一期:很难传递系统生成的事件。我认为它们在被处理后会被销毁。所以我将事件的数据复制到*and this does not work*并传递了它。 (我也试图复制这个事件,但是这不起作用。)

namedtuple