Solved Connecting signals and slots
-
I want to connect the signals and slots of the lcd and slider widgets.
I have created my own slider class, in which a QSlider object is created.
The lcd object is created inside main.cpp.
How do I connect these two widgets together?
What have I done wrong?I get the following errors:
main.cpp:
#include <QSlider> #include <QLCDNumber> #include <QApplication> #include <QVBoxLayout> #include "slider.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); Slider *slider = new Slider(Qt::Horizontal); slider->setRange(-100, 100); slider->setValue(20); QLCDNumber *lcd = new QLCDNumber; lcd->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); connect(slider, &Slider::valueChanged, lcd, &QLCDNumber::display); QWidget *top = new QWidget; QVBoxLayout *layout = new QVBoxLayout(top); layout->addWidget(slider); layout->addWidget(lcd); top->show(); return app.exec(); }
slider.cpp:
#include "slider.h" Slider::Slider(Qt::Orientation orient, QWidget *parent) : QWidget(parent) { m_slider = new QSlider(orient); QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(m_slider); setLayout(layout); connect(m_slider, &QSlider::valueChanged, this, &Slider::setValue ); } void Slider::setRange(int min, int max) { m_slider->setRange(min, max); } void Slider::setValue(int newValue) { if (newValue != m_value) { m_slider->setValue(newValue); m_value = newValue; emit valueChanged(newValue); } }
slider.h:
#ifndef SLIDER_H #define SLIDER_H #include <QSlider> #include <QVBoxLayout> #include <QLCDNumber> class QSlider; class Slider : public QWidget { Q_OBJECT public: Slider(Qt::Orientation orient = Qt::Horizontal, QWidget *parent = 0); void setRange(int min, int max); public slots: void setValue(int newValue); signals: void valueChanged(int newValue); private: QSlider *m_slider; int m_value; }; #endif // SLIDER_H
-
Hi! The image-upload feature on our forum is broken, you might see the picture but other users don't. Please upload your image to a image hoster of your choice (e.g. postimage.org) and embed the pic here with the following markup:
![alternate text](image-url)
. See also How to insert image on this forum and Hitchhiker's Visual Guide to the Qt Forum. -
You might want to check with the string-based connect version
connect(slider, SIGNAL(valueChanged(int) ), lcd, SLOT(display(int));
You have most likely have a problem with the fifth case of too much complexity for functor-based connect
-
@Wieland
Funnily, I see the picture ;)Is there a pattern?
-
@koahnig If I understood Tero's explanation correctly, it's pure luck: the forum is distributed over a couple of servers and thanks to some bug they don't share their image files. So you can see an image if the website you're looking at now comes from the same machine that the user uploaded the image to.
-
@koahnig
I have now replaced it as you said with:QObject::connect(slider, SIGNAL(valueChanged(int)), lcd, SLOT(display(int)));
and it works.
Thanks.But why doesn't it work using function pointers?
I am using Qt 5.8.0 with Qt Creator. -
Frankly, I do not know, yet.
The documentation just says that it is more complex with the functor-based connect and with string-based versions it is simple.
I love the functor because it is checked during compilation. So far, I assumed that the functor-based connect does not allow overloading. While trying to find the reference for you, I just saw that it is more complex. So either the documentation has changed since I started to use functors or I simply pushed it aside until I was comfortable with the functors and forgot. Now it is on my todo list ;) -
@JimmyMars said in Connecting signals and slots:
But why doesn't it work using function pointers?
Using the function pointers syntax, the signatures of the signal and slot must match. In this case, QLCDNumber::display(...) has three overloads:
void display(const QString &s) void display(int num) void display(double num)
You have to explicitly state which of these overloads you want to use:
QObject::connect(slider, &QSlider::valueChanged, lcd, static_cast<void (QLCDNumber::*)(int)>(&QLCDNumber::display));
-
@Wieland said in Connecting signals and slots:
QObject::connect(slider, &QSlider::valueChanged, lcd, static_cast<void (QLCDNumber::*)(int)>(&QLCDNumber::display));
Or, for shorter code:
QObject::connect(slider, &QSlider::valueChanged, lcd, QOverload<int>::of(&QLCDNumber::display));
Or even shorter still, if your compiler supports C++14:
QObject::connect(slider, &QSlider::valueChanged, lcd, qOverload<int>(&QLCDNumber::display));
(P.S. These exact examples, including @Wieland's code, can be found at http://doc.qt.io/qt-5/signalsandslots-syntaxes.html#selecting-overloaded-signals-and-slots )
@JimmyMars said in Connecting signals and slots:
But why doesn't it work using function pointers?
Because when the slot is an overloaded function, the compiler doesn't know which overload to choose.
static_cast
orQOverload
gives the compiler the information that it needs.In contrast, the string-based connection states exactly which overload to choose:
display(int)
.