10

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.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
kravitz
  • 973
  • 2
  • 10
  • 22
  • 3
    I'm really surprised to hear someone say that requiring information about a sender in the slot makes the code *more* generic. In general, slots are written so they don't require any knowledge of how they were activated (i.e., they could be called as methods directly as well). – Caleb Huitt - cjhuitt Jan 11 '11 at 18:05
  • Possible duplicate of [How to get sender widget with a signal/slot mechanism?](https://stackoverflow.com/questions/4046839/how-to-get-sender-widget-with-a-signal-slot-mechanism) – Aconcagua Apr 28 '18 at 20:24
  • @Aconcagua according to posting dates, my question was asked 9 month earlier than one you refer to – kravitz May 06 '18 at 16:30
  • @kravitz *"asked Oct 28* ***'10*** *at 20:18"*... – Aconcagua May 06 '18 at 20:55
  • @Aconcagua you're right, well then this may be a duplicate indeed. – kravitz May 07 '18 at 02:51
  • Actually, I don't think its that important *who* wrote the duplicate, just that they are *linked*. If the question is not closed too early to find an answer at all, there might be different approaches to the same problem found distributed over duplicate questions - or sometimes, answers on one duplicate are updated ("with version x.y, this trick does not work any more" or "since version x.y, there also exists...") while on the other one not. So its always good to easily get from one version of the same question to the other one and vice versa... – Aconcagua May 07 '18 at 06:07

4 Answers4

29

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()
kravitz
  • 973
  • 2
  • 10
  • 22
  • 2
    You must be aware of the waring in the documentation before using this function: http://doc.qt.nokia.com/4.7/qobject.html#sender – Patrice Bernassola Jan 10 '11 at 10:30
  • Patrice here is the link updated: https://qt-project.org/doc/qt-4.7/qobject.html#sender – eric Jul 28 '14 at 13:19
  • There are two warnings: **Warning:** This function violates the object-oriented principle of modularity. However, getting access to the sender might be useful when many signals are connected to a single slot. **Warning:** As mentioned above, the return value of this function is not valid when the slot is called via a `Qt::DirectConnection` from a thread different from this object's thread. Do not use this function in this type of scenario. https://web.archive.org/web/20101120154037/http://doc.qt.nokia.com:80/4.7/qobject.html#sender – Lorem Ipsum Oct 23 '18 at 16:19
1

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.

Jason Mock
  • 823
  • 1
  • 10
  • 19
0

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.

mins
  • 6,478
  • 12
  • 56
  • 75
-5

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

Martin Beckett
  • 94,801
  • 28
  • 188
  • 263
  • What is the name of the book and the author? I'm trying to figure out how to make a QLineEdit field double-clickable, so that the function which gets the signal: (1l) gets the name (handle?) of the QLineEdit field, and (2) can retrieve or set the text in the QLineEdit field. I'm looking for a book or tutorial that will show me how to do that. – Marc B. Hankin Jun 04 '19 at 21:06
  • That post was 8years ago, don't know relevant it is to latest Qt. – Martin Beckett Jun 05 '19 at 17:01