PDA

View Full Version : Will I learn to implement custom SIGNALS?



fatecasino
4th March 2011, 13:58
Reading examples and documentation I start to believe that making a custom SIGNAL is not a difficult task. Trying to do it though I realize that I cannot do it!!

Here's a simple example, that if I understand it I will be able to make more custom signals.


a line edit for number A
a line edit for number B
a line edit to present the result of the Multiplication


Here is the corresponding code:



MyDialog::MyDialog(QWidget *parent)
: QWidget(parent)
{

QLineEdit *numberA = new QLineEdit;
QLineEdit *numberB = new QLineEdit;

result = new QLineEdit;

numberA->setText("1.0");
numberB->setText("1.0");
result->setText("1.0");



vboxlayout = new QVBoxLayout(this);
vboxlayout->addWidget(numberA);
vboxlayout->addWidget(new QLabel("x"));
vboxlayout->addWidget(numberB);
vboxlayout->addWidget(new QLabel("="));
vboxlayout->addWidget(result);

setLayout(vboxlayout);
}


void MyDialog::showMultiplication(QString Astring,QString Bstring)
{
double A,B,Res;
QString ResString;


A= Astring.toDouble();
B= Bstring.toDouble();


Res = A*B;

ResString.setNum(Res);

result->setText(ResString);
}

QUESTION:
When the user inserts a new number (anywhere A or B) the multiplication result should be shown directly in the result line edit. The SLOT is obliously the showMultiplication(QString Astring,QString Bstring).

The SIGNAL should be something like
sendNewNumbersForMultiplication(QString ,QString )

BUT, I really cannot understand how to implement it!!
Any help?

pan
4th March 2011, 15:05
Maybe I miss-understand you?

But don't you just want to declare a signal in your header file. Then emit that signal when you get a signal (whichever you choose) from the Line edit object?

Like in your header:

signals:
void sendNewNumbersForMultiplication(QString ,QString );

Is this what you are trying to do?

fatecasino
4th March 2011, 15:17
yes, of course, I am trying to make the scenario described above to work. The user writes in a number and the system writes automatically the multiplication result in the result line edit.
The declaration of the SIGNAL will then be as you said:

signals:
void sendNewNumbersForMultiplication(QString ,QString );

But, what will I write into the implementation of the function in the .cpp file?


void MyDialog::sendNewNumbersForMultiplication(QString ,QString )
{

??

}

pan
4th March 2011, 15:25
No, you don't implement it, you emit it.



emit sendNewNumbersForMultiplication(numberA.text(),num berB.text());


Then you just connect your signal to a slot to display it. You implement the slot.

You do this from within a function in your class though. I'd guess, in your case from a slot connected to a signal coming from a QLineEdit object.

fatecasino
4th March 2011, 16:10
wait, because this is exactly the point I am getting confused!

QUESTION

emit sendNewNumbersForMultiplication(numberA.text(),num berB.text());
where does this line go into?




You implement the slot.
I think the slot is this:

void MyDialog::showMultiplication(QString Astring,QString Bstring)
{
double A,B,Res;
QString ResString;

A= Astring.toDouble();
B= Bstring.toDouble();

Res = A*B;
ResString.setNum(Res);
result->setText(ResString);
}





Then you just connect your signal to a slot to display it.
ok, I think this is the connection


connect(this, SIGNAL( sendNewNumbersForMultiplication(QString,QString ),this, SLOT(showMultiplication(QString ,QString )) );





in your case from a slot connected to a signal coming from a QLineEdit object.
I thought the SIGNAL was the sendNewNumbersForMultiplication(QString,QString ) function

pan
4th March 2011, 16:33
But when do you want your signal to be emitted?
Who is receiving the signal?

Looks to me you are doing all this within the one object? I'm not sure why, in this case you need to emit a signal, unless another object is going to listen for this signal...

In your case, just declare the QLineEdit objects in the header file and access them directly...

boudie
4th March 2011, 16:45
No need to create your own signal.

In MyDialog::MyDialog(QWidget *parent):


connect(numberA, SIGNAL(textChanged(QString)), this, SLOT(multiply(QString)));
connect(numberB, SIGNAL(textChanged(QString)), this, SLOT(multiply(QString)));


In MyDialog::multiply(QString):


A= numberA->text().toDouble();
B= numberB->text().toDouble();


Sorry, don't have any time to test, but you get the picture, I think...?

fatecasino
4th March 2011, 16:56
@boudie:

connect(numberA, SIGNAL(textChanged(QString)), this, SLOT(multiply(QString)));
connect(numberB, SIGNAL(textChanged(QString)), this, SLOT(multiply(QString)));


I don't want to use the built-in signals textChanged(QString) because the actual custom SIGNAL I want to implement is much more complicated than this simple example.
Anyway, if you notice carefully you'll see that the MyDialog::multiply(QString) does not know the value of the other QString. So, it will not work. Obviously I need to create a SIGNAL which sends two QStrings at a time:


sendNewNumbersForMultiplication(QString,QString )

SixDegrees
4th March 2011, 17:16
To broadcast a signal, you use the emit() statement, as noted above. You define the arguments it will send in your header file, also as noted above. At the point where you emit the signal, you provide it with the values of the arguments you want it to carry, which has been noted above.

fatecasino
4th March 2011, 22:13
To broadcast a signal, you use the emit() statement, as noted above. You define the arguments it will send in your header file, also as noted above. At the point where you emit the signal, you provide it with the values of the arguments you want it to carry, which has been noted above.

can you translate this with the implementation of this SIGNAL?

sendNewNumbersForMultiplication(QString,QString )

boudie
4th March 2011, 22:51
@boudie:
Anyway, if you notice carefully you'll see that the MyDialog::multiply(QString) does not know the value of the other QString. So, it will not work. Obviously I need to create a SIGNAL which sends two QStrings at a time:


sendNewNumbersForMultiplication(QString,QString )

As I notice carefully in your previous posts, both the QLineEdits and the slot are in the same class. So the slot has access to both QLineEdits and their values.

squidge
4th March 2011, 23:19
Your reason for a signal does not make sense. A signal is emitted because some action has occured. If you wish to multiply on a button being clicked, the signal will come from the button. If you wish to multiple on the text in an edit box being changed, then the signal will come from the edit box.

Now, if you wanted a signal which is emitted if the multiplied number is over 1000, then it would be a custom signal. In which case, you would put the definition of the signal in your header file, you would put the 'connect' statement in the class with the slot and emit the signal from your showMultiplication slot. Note that signals do not have implementations, only definitions.

Berryblue031
8th March 2011, 09:11
Ok so as I understand it you are simply asking how to create a signal with two parameters and how to trigger it when the value of one of the input boxes change?

in your class definition you define signals like this


class myObject : public QWidget
{
Q_OBJECT
signals:
void multiply(const QString& a, const QString& b);

private slots:
void onVariableChanged();
void doMultiplication(const QString& a, const QString& b);
...
};


then connect the signals and slots


connect(numberA, SIGNAL(textChanged(const QString&)), this, SLOT(onVariableChanged()));
connect(numberB, SIGNAL(textChanged(const QString&)), this, SLOT(onVariableChanged()));
connect(this, SIGNAL(multiply(const QString&, const QString&), this, SLOT(doMultiplication(const QString&, const QString&));


We use the text changed signal to trigger the creation of our more "complicated" multiplication signal and then emit it



void MyObject::onVariableChanged()
{
//Query any data we want here and send a new signal
emit multiply(numberA->text(), numberB->text());
}

void MyObject::doMultiplication(const QString& a, const QString& b)
{
double x = a.toDouble() * b.toDouble();
result->setText(QString::number(x));
}

stampede
8th March 2011, 10:44
Berryblue031 post
Ok, but here is a little confusion - you declare doMultiplication as a slot, and then use it as if it was a signal (with emit).
As noted in boudie's post, you have access to both lineEdits, so there is no need to send a signal in order to do multiplication - connect textChanged signal to onVariableChanged slot, and simply call multiplication method with values of both lineEdits:



class myObject : public QWidget
{
Q_OBJECT
private slots:
void onVariableChanged();
void doMultiplication(const QString& a, const QString& b);
...
};

// ...
connect(numberA, SIGNAL(textChanged(const QString&)), this, SLOT(onVariableChanged()));
connect(numberB, SIGNAL(textChanged(const QString&)), this, SLOT(onVariableChanged()));
//...

void MyObject::onVariableChanged(){
this->doMultiplication(numberA->text(), numberB->text());
}
There's no need to complicate such simple task:)

Berryblue031
8th March 2011, 12:57
Ok, but here is a little confusion - you declare doMultiplication as a slot, and then use it as if it was a signal (with emit).


Ahh you are right that is a typo on my part, I will fix it.


Reading examples and documentation I start to believe that making a custom SIGNAL is not a difficult task. Trying to do it though I realize that I cannot do it!! Here's a simple example, that if I understand it I will be able to make more custom signals.


The op's problem was in general that he didn't understand how to implement and emit a custom signal, the scenario he posted wasn't really a scenario where he absolutely needed to use signals slots but there is nothing wrong with doing so and it's a good enough example for learning how to emit a signal. Telling him how to solve the problem without using signals kind of defeats the purpose.