PDA

View Full Version : how to know which signal is called a certain slot?



Alex22
10th December 2015, 20:17
Hi,
There are 5 Classes and from each class I have 4 objects. When each object (each of these 20 objects) change , signal of that is emitted and calls a certain slot. for example:


connect(obj1_0, SIGNAL(sig1()), this, SLOT(myslot()));//obj1_0 is a type of Class1
connect(obj1_1, SIGNAL(sig1()), this, SLOT(myslot()));
connect(obj1_2, SIGNAL(sig1()), this, SLOT(myslot()));
connect(obj1_3, SIGNAL(sig1()), this, SLOT(myslot()));

connect(obj2_0, SIGNAL(sig2()), this, SLOT(myslot()));//obj2_0 is a type of Class2 deference from Class1
connect(obj2_1, SIGNAL(sig2()), this, SLOT(myslot()));
connect(obj2_2, SIGNAL(sig2()), this, SLOT(myslot()));
connect(obj2_3, SIGNAL(sig2()), this, SLOT(myslot()));
.
.
.
.
connect(obj5_0, SIGNAL(sig5()), this, SLOT(myslot()));//obj5_0 is a type of Class5 deference from Class1, Class2, Class3, Class4
connect(obj5_1, SIGNAL(sig5()), this, SLOT(myslot()));
connect(obj5_2, SIGNAL(sig5()), this, SLOT(myslot()));
connect(obj5_3, SIGNAL(sig5()), this, SLOT(myslot()));


I am using QSignalMapper for this and defined 5 objects of this class for all of Class1,...,Class5 like obj1_signalmapper, obj2_signalmapper,..., obj5_signalmapper by a "int id". But I need to know which object and from which kind of class send signal(for example know first: obj1_2 send and seccond:from type of Class1). I can know obj id but I can not know this object is for which class because obj1_3 has the same "id" that obj5_3 has.

Thanks for any help.

d_stranz
10th December 2015, 20:30
Inside your slot, QObject::sender() will tell you which instance of which object sent the signal. If Class1 - Class5 are different classes, then you will have to do a qobject_cast< Class1 * >( sender() ) (and so forth) and check for a non-NULL pointer to first see what type of class sent the signal.

Alex22
10th December 2015, 21:37
Thanks but this dos not work and for all senders give NULL. it could be because of using obj1_0 = new Class1 in a ForLoop when i=0 and obj1_1 is the same when i=1, .... In other word, obj1_0, obj1_2,..... are defined in loop like this:


for(int i=0; i<4; i++)
{
obj1 = new Class1//this produces 4 objects from Class1 (obj1_0, obj1_1,..., obj1_4)
obj2 = new Class2//this produces 4 objects from Class1 (obj1_0, obj1_1,..., obj1_4)
obj3 = new Class3
obj4 = new Class4
obj5 = new Class5
//here i used QSignalMapper and other things
}


thanks for any help

d_stranz
10th December 2015, 22:05
//this produces 4 objects from Class1 (obj1_0, obj1_1,..., obj1_4)

No it doesn't. It produces 4 instances of Class1, all of which are assigned to the single variable obj1. This code won't even compile, and even if it did, each time through the loop you are reassigning obj1 - obj5 to new instances of the classes and the values from the previous time through the loop are lost (and result in a memory leak).

Why don't you post your real code instead of making something up so we can see what you actually might be doing wrong instead of having to guess?

Alex22
10th December 2015, 22:46
No it doesn't. It produces 4 instances of Class1, all of which are assigned to the single variable obj1. This code won't even compile, and even if it did, each time through the loop you are reassigning obj1 - obj5 to new instances of the classes


thanks. this is an example in Qt assistance for QSignalMapper:


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]);//here in a loop Qt uses that I used too
connect(button, SIGNAL(clicked()), signalMapper, SLOT(map()));
signalMapper->setMapping(button, texts[i]);
gridLayout->addWidget(button, i / 3, i % 3);
}

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

setLayout(gridLayout);
}



the values from the previous time through the loop are lost

Because of using QSignalmapper it could be saved with an id.
thanks for any help

Vikram.Saralaya
10th December 2015, 22:55
The difference is in the example the pushbuttons are added to a grid layout which takes ownership of the button. Hence no memory leak. d_stranz was pointing at your rough sketch code where that part is missing..

Alex22
10th December 2015, 23:06
The difference is in the example the pushbuttons are added to a grid layout which takes ownership of the button. Hence no memory leak. d_stranz was pointing at your rough sketch code where that part is missing..

thanks, my code has QgridLayout too. and looks like above example. deferences are: 1- i have PushButton and even CheckBox, ComboBox, QLineEdit, QSpinBox ( these are my 5 Classes) and for each of these calasses i create 4 objects in that loop. 2-then i used a QSignalMapper object for each these classes like: pushbutton_signalmapper, chekbox_signalmapper,..., spnbox_signalmapper . other thing are like the example.
thanks for more help.

Vikram.Saralaya
11th December 2015, 08:26
You probably need this:

void QSignalMapper::setMapping(QObject * sender, QWidget * widget)

Pass checkbox, combobox etc. which are all QWidgets. Then in the slot you know which widget sent the signal..

Alex22
11th December 2015, 09:29
@Vikram, Thanks but in this way i lost id number of each object for example by this, that you told, i can know sender is from Class1 but which object of this class send? by "void setMapping(QObject * sender, int id)" i can know object number and i can not know this object is from which class. now I could know which object (id) send and can not know this is from which class. One idea is I define 2 objects of QSignalMapper for each class (then i have 10 objects of QSignalMapper like:


pushbutton_id_signalMapper->setMapping(QObject * sender, int id)
pushbutton_type_signalMapper->setMapping(QObject * sender, QWidget * widget)

chekbox_id_signalMapper->setMapping(QObject * sender, int id)
chekbox_type_signalMapper->setMapping(QObject * sender, QWidget * widget)
.
.
.
spnbox_id_signalMapper->setMapping(QObject * sender, int id)
spnbox_type_signalMapper->setMapping(QObject * sender, QWidget * widget)

If I used QWidget * widget for identifying the class type, by what function I can know sender type? I mean when for example sender is PushButton then how can I know this:


pushbutton_type_signalMapper->whatIsThisFunctionThatTellUsTheClassTypeToUseInsid eSlot()//what function?


thanks for any help!!!

Vikram.Saralaya
11th December 2015, 10:06
i can know sender is from Class1 but which object of this class send?
You get QWidget* as a parameter in the slot after mapping. you already know that pushButton, checkbox or lineEdit can send the signal. So:


QPushButton *pushBtn = qobject_cast<QPushButton*>(widget);
if(pushBth)
{
qDebug() << "QPushButton sent the signal " << pushBtn->text();
// Do whatever you want.
return;
}

QLineEdit *lineEdit = qobject_cast<QLineEdit*>(widget);
if(lineEdit)
{
qDebug() << "QLineEdit sent the signal " << lineEdit->text();
// Do whatever you want.
return;
}

// Similarly for other widgets

PS: If you need id, name etc it doesn't make sense to create a signal mapper for each. Subclass pushbutton, define id in your custom button and then as explained in the code above cast QWidget* to your custom button and customButton->GetId() or some accessor you defined should give you id, name or anything else.

Alex22
11th December 2015, 10:31
@Vikram.Saralaya thanks so much!!!
if I could set an id number for each object without using QSignalMapper, then I will solve my problem. How can I do this? For example there are 100 CheckBox and we want to give number id from 1000 up 1100, is there any setIdNum() function for this Widget and another widgets?

Vikram.Saralaya
11th December 2015, 11:23
Use properties with your buttons and checkboxes.
bool QObject::setProperty(const char * name, const QVariant & value)

Example:

widget->SetProperty("id", 1001);

Retrieve the id in the slot:

int id = widget->property("id").toInt();

Alex22
11th December 2015, 12:42
Use properties with your buttons and checkboxes.
bool QObject::setProperty(const char * name, const QVariant & value)

Example:

widget->SetProperty("id", 1001);

Retrieve the id in the slot:

int id = widget->property("id").toInt();

@Vikram.Saralaya, man this works so nice!!!
thanks a lot for your great help:cool: