How do I use the signal parameter in the slot?
-
I wrote a debouced function to avoid sending signals too frequently, but I don't know how to use the signal parameter in the slot. How should this be implemented?
#include <QApplication> #include <QTimer> #include <QSlider> class Debounced { public: template <typename Func1, typename Func2> static inline typename std::enable_if<QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1, QMetaObject::Connection>::type connect(const typename QtPrivate::FunctionPointer<Func1>::Object* sender, Func1 signal, const QObject* context, Func2 slot, Qt::ConnectionType type = Qt::AutoConnection) { QTimer* timer = new QTimer((QObject*)context); timer->setSingleShot(true); QObject::connect(sender, signal, timer, [=]() {timer->start(200); }); return QObject::connect(timer, &QTimer::timeout, context, std::move(slot), type); } }; int main(int argc, char* argv[]) { QApplication app(argc, argv); auto t = new QSlider; //Debounced::connect(t, &QSlider::valueChanged, t, []() {printf("111 "); }); Debounced::connect(t, &QSlider::valueChanged, t, [](int v) {printf("%d ", v); }); t->show(); return app.exec(); } -
In the end, I used this way to achieve it. I cant to write a template that can accommodate any number of parameters.
template <typename T> struct lambda_traits : lambda_traits<decltype(&T::operator())> {}; template <typename ClassType, typename ReturnType, typename... Args> struct lambda_traits<ReturnType(ClassType::*)(Args...) const> { static const std::size_t arity = sizeof...(Args); using Tuple = std::tuple<Args...>; }; class Debounced { public: template <typename Func1, typename Func2> static inline typename std::enable_if<lambda_traits<Func2>::arity == 0, QMetaObject::Connection>::type connect(const typename QtPrivate::FunctionPointer<Func1>::Object* sender, Func1 signal, const QObject* context, Func2 slot, Qt::ConnectionType type = Qt::AutoConnection) { QTimer* timer = new QTimer((QObject*)context); timer->setSingleShot(true); QObject::connect(sender, signal, timer, [=]() { timer->start(200); }); return QObject::connect(timer, &QTimer::timeout, context, std::move(slot), type); } template <typename Func1, typename Func2> static inline typename std::enable_if<lambda_traits<Func2>::arity == 1, QMetaObject::Connection>::type connect(const typename QtPrivate::FunctionPointer<Func1>::Object* sender, Func1 signal, const QObject* context, Func2 slot, Qt::ConnectionType type = Qt::AutoConnection) { QTimer* timer = new QTimer((QObject*)context); timer->setSingleShot(true); using ParamType0 = std::tuple_element<0, lambda_traits<Func2>::Tuple>::type; ParamType0* p0 = new ParamType0; QObject::connect(sender, signal, timer, [=](ParamType0 p) {*p0 = p; timer->start(200); }); return QObject::connect(timer, &QTimer::timeout, context, [=]() {slot(*p0); }, type); } }; #include <QApplication> #include <QTimer> #include <QSlider> #include <QDoubleSpinBox> int main(int argc, char* argv[]) { QApplication app(argc, argv); auto w = new QWidget(); auto sl = new QSlider(w); auto dsp = new QDoubleSpinBox(w); w->show(); sl->move(10,30); w->resize(50, 200); Debounced::connect(sl, &QSlider::valueChanged, sl, []() {printf("222 "); }); Debounced::connect(sl, &QSlider::valueChanged, sl, [](int v) {printf("%d ", v); }); Debounced::connect(dsp, QOverload<double>::of(&QDoubleSpinBox::valueChanged), dsp, [](double v) {printf("%f ", v); }); return app.exec(); } -
I wrote a debouced function to avoid sending signals too frequently, but I don't know how to use the signal parameter in the slot. How should this be implemented?
#include <QApplication> #include <QTimer> #include <QSlider> class Debounced { public: template <typename Func1, typename Func2> static inline typename std::enable_if<QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1, QMetaObject::Connection>::type connect(const typename QtPrivate::FunctionPointer<Func1>::Object* sender, Func1 signal, const QObject* context, Func2 slot, Qt::ConnectionType type = Qt::AutoConnection) { QTimer* timer = new QTimer((QObject*)context); timer->setSingleShot(true); QObject::connect(sender, signal, timer, [=]() {timer->start(200); }); return QObject::connect(timer, &QTimer::timeout, context, std::move(slot), type); } }; int main(int argc, char* argv[]) { QApplication app(argc, argv); auto t = new QSlider; //Debounced::connect(t, &QSlider::valueChanged, t, []() {printf("111 "); }); Debounced::connect(t, &QSlider::valueChanged, t, [](int v) {printf("%d ", v); }); t->show(); return app.exec(); }@John-Van I don't understand the problem.
A parameter passed from signal to slot is just that: a function/lambda/method parameter and you use is it like any other parameter.Please explain better what is not clear/does not work. -
@John-Van I don't understand the problem.
A parameter passed from signal to slot is just that: a function/lambda/method parameter and you use is it like any other parameter.Please explain better what is not clear/does not work.@jsulm I want to write a common function to avoid sending signals too frequently, but the ‘timeout’ slot has no parameter, so I don’t know how to pass the parameter from the signal to the slot. Therefore, the line ‘Debounced::connect’ cannot compile successfully.
-
@jsulm I want to write a common function to avoid sending signals too frequently, but the ‘timeout’ slot has no parameter, so I don’t know how to pass the parameter from the signal to the slot. Therefore, the line ‘Debounced::connect’ cannot compile successfully.
@John-Van Would be good if you would post the error message.
You can use a lambda as slot to pass parameter to a slot which is not provided by the signal.
Something like:QObject::connect(timer, &QTimer::timeout, context, [some_parameter]() { slot(some_parameter); }, type); -
In the end, I used this way to achieve it. I cant to write a template that can accommodate any number of parameters.
template <typename T> struct lambda_traits : lambda_traits<decltype(&T::operator())> {}; template <typename ClassType, typename ReturnType, typename... Args> struct lambda_traits<ReturnType(ClassType::*)(Args...) const> { static const std::size_t arity = sizeof...(Args); using Tuple = std::tuple<Args...>; }; class Debounced { public: template <typename Func1, typename Func2> static inline typename std::enable_if<lambda_traits<Func2>::arity == 0, QMetaObject::Connection>::type connect(const typename QtPrivate::FunctionPointer<Func1>::Object* sender, Func1 signal, const QObject* context, Func2 slot, Qt::ConnectionType type = Qt::AutoConnection) { QTimer* timer = new QTimer((QObject*)context); timer->setSingleShot(true); QObject::connect(sender, signal, timer, [=]() { timer->start(200); }); return QObject::connect(timer, &QTimer::timeout, context, std::move(slot), type); } template <typename Func1, typename Func2> static inline typename std::enable_if<lambda_traits<Func2>::arity == 1, QMetaObject::Connection>::type connect(const typename QtPrivate::FunctionPointer<Func1>::Object* sender, Func1 signal, const QObject* context, Func2 slot, Qt::ConnectionType type = Qt::AutoConnection) { QTimer* timer = new QTimer((QObject*)context); timer->setSingleShot(true); using ParamType0 = std::tuple_element<0, lambda_traits<Func2>::Tuple>::type; ParamType0* p0 = new ParamType0; QObject::connect(sender, signal, timer, [=](ParamType0 p) {*p0 = p; timer->start(200); }); return QObject::connect(timer, &QTimer::timeout, context, [=]() {slot(*p0); }, type); } }; #include <QApplication> #include <QTimer> #include <QSlider> #include <QDoubleSpinBox> int main(int argc, char* argv[]) { QApplication app(argc, argv); auto w = new QWidget(); auto sl = new QSlider(w); auto dsp = new QDoubleSpinBox(w); w->show(); sl->move(10,30); w->resize(50, 200); Debounced::connect(sl, &QSlider::valueChanged, sl, []() {printf("222 "); }); Debounced::connect(sl, &QSlider::valueChanged, sl, [](int v) {printf("%d ", v); }); Debounced::connect(dsp, QOverload<double>::of(&QDoubleSpinBox::valueChanged), dsp, [](double v) {printf("%f ", v); }); return app.exec(); } -
J John Van has marked this topic as solved on