简体   繁体   中英

How to determine who emitted the signal?

I develop an application on PyQt, I like the signal-slot model, but is there any way to determine the emitter of signal? I hope that there is a way, because it will let to write more generic code without defining lots of slots for each similar signal.

I think that I opened a question too early, because I found an answer on google by myself. When slot is activated by emitter, the pointer of emitter stored, and can be retrieved by

QObject::sender()

and as a result can be accessed in PyQt by:

@QtCore.pyqtSlot()
def someSlot(self):
    self.sender()

You might want to look into the QSignalMapper class, as it provides a means to associate either an int, string, or widget paramters to an object that sends a given signal. The main limitation is that the signal/slot being mapped needs to be parameter-less.

C++ example from the QT4.7 documentation :

 ButtonWidget::ButtonWidget(QStringList texts, QWidget *parent)
     : QWidget(parent)
 {
     signalMapper = new QSignalMapper(this);

     QGridLayout *gridLayout = new QGridLayout;
     for (int i = 0; i < texts.size(); ++i) {
         QPushButton *button = new QPushButton(texts[i]);
         connect(button, SIGNAL(clicked()), signalMapper, SLOT(map()));
         signalMapper->setMapping(button, texts[i]);
         gridLayout->addWidget(button, i / 3, i % 3);
     }

     connect(signalMapper, SIGNAL(mapped(const QString &)),
             this, SIGNAL(clicked(const QString &)));

     setLayout(gridLayout);
 }

You can find a PyQT4 example here , however when I have a chance I'll try to add a simple PyQT4 example.

The Qt5 option is to use a signal mapper. It's an object able to receive a signal from different sources and call a single callback function (slot) with a unique parameter. The function then uses the parameter to determine the source. Let's say we want to connect two check boxes to the same slot:

Create a signal mapper:

signalMapper = QSignalMapper()

Associate a mapping of type int with the callback function:

signalMapper.mapped[int].connect(sync_checkboxes)

Connect the widgets triggering the signals to the mapper:

checkbox_1.clicked.connect(signalMapper.map)
checkbox_2.clicked.connect(signalMapper.map)

Define the mapping between the sources and the int values (0 and 1):

signalMapper.setMapping(checkbox_1, 0)
signalMapper.setMapping(checkbox_2, 1)

Now the callback accepting the integer value:

def sync_checkboxes(index):
    if index == 0:
        ....

Documentation (of poor quality):

The mapping can be void (source object reference is passed), integer-based, string-based or object-based. From what I understand from the documentation, the different types can be mixed, the mapper identifies which mapping is associated to the source, and calls the appropriate callback. What happens if multiple mappings have been set for the same source is not said, so some experiment is required. It's a pity the documentation is so poor for a such interesting product.

Note that this doesn't tell you eg. which cell in a grid control wasedited - just the grid control handle itself.

There is a new Advanced Qt book out which goes into a lot of detail about advanced signal/slot routing

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM