Qt connect() without QObject or slots - c++

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();} );

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

C++ QT5 TextEdit append

connect
{connect(ui->add, SIGNAL(clicked()),ui->text,SLOT(text.append(line)));}
question
I want to add a function that is appended to the lower text window when I enter a string in the upper line window and click Add, but the function does not work.
You can connect your button to a lambda slot to do what you want in Qt5 style like this:
connect(ui->add, &QPushButton::clicked, this, [this]() {
ui->text->append(line);
} );
I assume your 'ui->add' is the button and 'ui->text' is the QTextEdit? If that's the case, as suggested by Farshid616, you need to use a lambda. Why? two reasons:
In Qt's Signals & Slots, if you want to pass an argument to the SLOT, you need to return it in the SIGNAL. In your case, clicked() doesn't return anything (see function signature here), while append(const QString &text) takes a string (see here).
Lambdas are an easy way to overcome this issue by using connect(const QObject *sender, PointerToMemberFunction signal, Functor functor), where we use a lambda as the functor (see an example bellow). This is an overloaded connect call (see the signature here).
QObject::connect(your_button, &QPushButton::clicked, [this]() {
your_text_edit->append(your_line_edit->text());
} );
Note: you need to "capture" this (current object pointer) in the lambda in order to be allowed to access your_text_edit and your_line_edit, which are members of this (i.e. this->your_text_edit and this->your_line_edit). The capture of this is by reference. You can see this more clearly if we write a bit more explicitly the code above:
QObject::connect(this->your_button, &QPushButton::clicked, [this]() {
this->your_text_edit->append(this->your_line_edit->text());
} );

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); } );

How to pass an extra variable to a Qt slot

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);
}

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.