How to pass an extra variable to a Qt slot - c++

I would like to know how to pass a separate variable into a slot.
I cant seem to get it to work. Is there some way around this?
This is my code:
QTimer * timer = new QTimer();
connect(timer,SIGNAL(timeout()),this,SLOT(method(MYVARIABLE)));
timer->start(4000);

If you don't want to declare MYVARIABLE in your class, but instead to have it tied to this particular signal/slot connection, you can connect the signal to a C++11 lambda using Qt5's new singal/slot syntax and then call your slot with that lambda.
For example you could write:
QTimer * timer = new QTimer();
connect(timer, &QTimer::timeout, [=]() {
method(MYVARIABLE);
});
timer->start(4000);
Another solution if you can't use C++11 and Qt5 is to use Qt's Property System to attach a variable to your QTimer*. This can be done with QObject::setProperty().
Then in the slot you could use QObject::sender() to get your QTimer* and read the property back using QObject::property().
However, note that it's not a very clean solution, and borderline abuse of the property system.

from http://doc.qt.io/qt-5/signalsandslots.html
The rule about whether to include arguments or not in the SIGNAL() and
SLOT() macros, if the arguments have default values, is that the
signature passed to the SIGNAL() macro must not have fewer arguments
than the signature passed to the SLOT() macro.
you can try this
QTimer * timer = new QTimer();
connect(timer,SIGNAL(timeout()),this,SLOT(methodSlot()));
timer->start(4000);
methodSlot()
{
method(MYVARIABLE);
}

Related

Pass multiples arguments to a slot Qt

I'm using a Qt horizontal slider and I want to connect it's valueChanged signal to a slot I defined. However I need to access a specific member inside this slot to modify a variable thanks to the int I set with the slider. Until now, my connect line looks like this :
connect(slider, SIGNAL(valueChanged(int)), this, SLOT(setVariable(int)));
Is it possible to pass more than one argument to my slot ?What i'd like to do is something like :
connect(slider, SIGNAL(valueChanged(int)), this, SLOT(setVariable(int, pointerToMember*)));
If not how can I proceed ?
Thanks
Yes, you can, but you need to use new connect style, so you can pass lambda function
connect(slider, &QAbstractSlider::valueChanged, this, [=](int &new_value) { this->setVariable(new_value, ... );});
Edit:
This works only in Qt5 and above

Connecting function to dynamically made QPushButton

Sorry, this question is probably duplicate but i have to ask since i can't make it work.
I am dynamically making QPushButtons with for loop like this.
for (int var = 0; var < size; ++var) {
QPushButton *copyr = new QPushButton("copy");
...
}
I am successfully adding those new widgets to layout but i cant bind an function on them.I am trying to connect that button on SLOT like as many sources on the internet had suggested:
connect (copyr , SIGNAL( clicked() ), this, SLOT( c2c(txt) ) );
but i can't make it work, and i am kp getting an error like :
No such SLOT ClassName::c2c(txt)
event it's normally defined in .h file and it exists in .cpp file also.
Any ides why is this happening and how too fix it?
First of all, use the new syntax for connections:
connect(copyr, &QPushButton::clicked, this, &ClassName::c2c);
However, you cannot connect a signal that does not provide a parameter to a slot that expects one. Here, you have multiple options:
Remove the parameter from the slot entirely and get the value from within the slot.
Provide a default parameter in the slot declaration so it can be called without arguments
Wrap the connection in a lambda if you want a parameter from the connecting code to arrive at the slot like this:
connect( copyr, &QPushButton::clicked, [this, txt](){ this->c2c(txt); } );

Qt custom QPushButton clicked signal

I want to send two integers, string and fret, to a SLOT that will process the location of the button that was pressed. The SIGNAL and SLOT argument have to match so I am thinking I need to reimplement the QPushButton::clicked event method. Problem is I am new to Qt and could use some direction.
connect(&fretBoardButton[string][fret], SIGNAL(clicked()), this, SLOT (testSlot()));
If you use the C++11 connection syntax you can use a lambda with calls testSlot with your string and fret arguments:
connect(&fretBoard[string][fret], &QPushButton::clicked, [this, string, fret]() {
testSlot(string, fret);
});
This code creates a lambda using the [captures, ...](arguments, ...) { code } syntax. When you make the connection it captures the string and fret variable values, and will then pass them on to testSlot when the button is clicked.
There are Two approaches you could use to add the string and fret information. one is to use the sender() function to get the button which emitted the signal. you can the access fret and string if they are members of your button class so in the SLOT you would have.
MyPushButton *button = (MyPushButton *)sender();
button.getFret();
button.getString();
However since you are already subClassing QPushButton you could use a private SLOT to catch the buttonClicked signal and re-emit a signal with the right values.
In the constructor
connect(this, SIGNAL(clicked()), this, SLOT(reemitClicked()));
and then the reemit SLOT
void MyPushButton::reemitClicked()
{
emit clicked(m_fret, m_string);
}
be sure to add the appropriate private slot and public signal to you class
https://doc.qt.io/archives/qq/qq10-signalmapper.html see this artical for a good discussion on various ways to add an argument to signal.

Qt connect() without QObject or slots

I know what I am trying to achieve is possible, because I can do it with a lambda expression and I have done it before (Few months ago I just don't remember the syntax). Basically, I want to connect a function to a timer/button/etc. to facilitate the workings of an event.
Here is my working code:
connect( &renderTimer, &QTimer::timeout, [ = ]() {
onTimerUpdate();
} );
That uses a lambda to connect to the slot. I want to just reference the function itself instead of using a lambda expression. I have tried inserting the method onTimerUpdate() and &onTimerUpdate none of which work. I don't want to use QObject or any of it's pre-generated bullcrap — nor do I want to define slots within my class. I want to, quite simply, connect it directly to my function.
This is the format when connecting to a member function:
QObject::connect(&renderTimer, &QTimer::timeout, this, &ArclightGLWidget::onTimerUpdate);
This is the format when connecting to a free funciton (same for lambda)
QObject::connect(&renderTimer, &QTimer::timeout, onTimerUpdate);
And this is the format when connecting to a static member function:
QObject::connect(&renderTimer, &QTimer::timeout, SomeType::onTimerUpdate);
Presumably this call is being made inside the class of which onTimerUpdate is a method. If so you can call:
connect(&renderTimer, &QTimer::timeout, this, &foo::onTimerUpdate);
This is preferable to the lambda because Qt will manage the connection and you will also be able to call sender() in the slot.
However if you are within the class in which onTimerUpdate is a method you can also use the lambda exactly as you have put in the question:
connect( &renderTimer, &QTimer::timeout, [=](){onTimerUpdate();} );

Qt: connecting signal to slot having more arguments

I want to connect a signal clicked() from the button to a slot of different object.
Currently I connect signal to helper method and call desired slot from there:
connect(button, SIGNAL(clicked()), this, SLOT(buttonClicked()));
void buttonClicked() { // Helper method. I'd like to avoid it.
someObject.desiredSlot(localFunc1(), localFunc2());
}
But maybe there is a more simple and obvious way to do this?
is this what you want to do:
the signal clicked should be connected to the "desiredSlot" which takes two arguments that are returned by localFunc1 & 2 ??
this is not possible, as you can read in the QT docs. A slot can take less arguments than provided by the signal - but not the opposite way! (The documentation says "This connection will report a runtime error")
This ought to work with the new signal/slot mechanism in qt 5:
connect( button, &QPushButton::clicked, [&](){ someObject.desiredSlot( localFunc1(), localFunc2() ); } );
You will need to adjust the lambda capture to your needs.
In some cases, default arguments may help, e.g. declare desiredSlot as:
desiredSlot(int a=0, int b=0)
You cannot access members in default argument though.
That is not the way to connect signals and slots in QT. You should use:
connect(button, SIGNAL(clicked()), receiver, SLOT(slotToBeCalled());
Have a look at the QT documentation.