QTimer with lambda functions
-
wrote on 22 Jan 2019, 19:07 last edited by
I'm trying to follow this hint to send a signal with a parameter:
class CustomDelegateOperators : public QStyledItemDelegate { Q_OBJECT public: CustomDelegateOperators(QObject *parent = nullptr); QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; void setEditorData(QWidget *editor, const QModelIndex &index) const; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const; signals: void validationFailed(QModelIndex index) const; }; void CustomDelegateOperators::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &idx) const { switch (index.column()) { case MODEL_OPERATORS_COL_NAME: { QLineEdit *item = qobject_cast<QLineEdit *>(editor); QRegExp rx("^(?!\\s*$).+"); QRegExpValidator *validator = new QRegExpValidator(rx); QString value = item->text(); int pos = 0; if (validator->validate(value, pos) == QValidator::Acceptable) model->setData(idx, value, Qt::EditRole); else QTimer::singleShot(10, this, [idx] () { &CustomDelegateOperators::validationFailed(idx); }); break; } default: QStyledItemDelegate::setModelData(editor, model, index); break; } }
but the compiler says:
'this' cannot be implicitly captured in this context
cannot take the address of an rvalue of type 'void'
no matching function for call to 'singleShot'and other 60 lines (but QtCreator doesn't allow to copy paste more than one line at time...)
Why it doesn't work here? -
Hi,
Remove the &.
You should also add the emit keyword, that will make things clearer.And you have to pass
this
explicitly[edit: Added missing
this
handling SGaist] -
wrote on 22 Jan 2019, 19:23 last edited by
Like this?
QTimer::singleShot(10, this, [idx] () { emit CustomDelegateOperators::validationFailed(idx); });
it quite the same error:
'this' cannot be implicitly captured in this context
cannot call member function 'void CustomDelegateOperators::validationFailed(QModelIndex) const' without object
no matching function for call to 'singleShot'I cannot fully understand what these messages really mean.
-
Like this?
QTimer::singleShot(10, this, [idx] () { emit CustomDelegateOperators::validationFailed(idx); });
it quite the same error:
'this' cannot be implicitly captured in this context
cannot call member function 'void CustomDelegateOperators::validationFailed(QModelIndex) const' without object
no matching function for call to 'singleShot'I cannot fully understand what these messages really mean.
@Mark81
Hi
What aboutQTimer::singleShot(10, this, [this, idx] () { emit validationFailed(idx); });
Compiles here. (using Mainwindow as slot holder)
-
wrote on 22 Jan 2019, 19:59 last edited by
It doesn't compile here:
customdelegateoperators.cpp: In member function 'virtual void CustomDelegateOperators::setModelData(QWidget*, QAbstractItemModel*, const QModelIndex&) const': customdelegateoperators.cpp:70:17: error: no matching function for call to 'QTimer::singleShot(int, const CustomDelegateOperators*, CustomDelegateOperators::setModelData(QWidget*, QAbstractItemModel*, const QModelIndex&) const::<lambda()>)' }); ^ In file included from C:\Qt\5.11.1\mingw53_32\include\QtCore/QTimer:1:0, from customdelegateoperators.cpp:4: C:\Qt\5.11.1\mingw53_32\include\QtCore/qtimer.h:83:17: note: candidate: static void QTimer::singleShot(int, const QObject*, const char*) static void singleShot(int msec, const QObject *receiver, const char *member); ^ C:\Qt\5.11.1\mingw53_32\include\QtCore/qtimer.h:83:17: note: no known conversion for argument 3 from 'CustomDelegateOperators::setModelData(QWidget*, QAbstractItemModel*, const QModelIndex&) const::<lambda()>' to 'const char*' C:\Qt\5.11.1\mingw53_32\include\QtCore/qtimer.h:84:17: note: candidate: static void QTimer::singleShot(int, Qt::TimerType, const QObject*, const char*) static void singleShot(int msec, Qt::TimerType timerType, const QObject *receiver, const char *member); ^ C:\Qt\5.11.1\mingw53_32\include\QtCore/qtimer.h:84:17: note: candidate expects 4 arguments, 3 provided C:\Qt\5.11.1\mingw53_32\include\QtCore/qtimer.h:102:24: note: candidate: template<class Duration, class Func1> static void QTimer::singleShot(Duration, const typename QtPrivate::FunctionPointer<Func2>::Object*, Func1) static inline void singleShot(Duration interval, const typename QtPrivate::FunctionPointer<Func1>::Object *receiver, Func1 slot) ^ C:\Qt\5.11.1\mingw53_32\include\QtCore/qtimer.h:102:24: note: template argument deduction/substitution failed: C:\Qt\5.11.1\mingw53_32\include\QtCore/qtimer.h: In substitution of 'template<class Duration, class Func1> static void QTimer::singleShot(Duration, const typename QtPrivate::FunctionPointer<Func2>::Object*, Func1) [with Duration = int; Func1 = CustomDelegateOperators::setModelData(QWidget*, QAbstractItemModel*, const QModelIndex&) const::<lambda()>]': customdelegateoperators.cpp:70:17: required from here C:\Qt\5.11.1\mingw53_32\include\QtCore/qtimer.h:102:24: error: no type named 'Object' in 'struct QtPrivate::FunctionPointer<CustomDelegateOperators::setModelData(QWidget*, QAbstractItemModel*, const QModelIndex&) const::<lambda()> >' In file included from C:\Qt\5.11.1\mingw53_32\include\QtCore/QTimer:1:0, from customdelegateoperators.cpp:4: C:\Qt\5.11.1\mingw53_32\include\QtCore/qtimer.h:107:24: note: candidate: template<class Duration, class Func1> static void QTimer::singleShot(Duration, Qt::TimerType, const typename QtPrivate::FunctionPointer<Func2>::Object*, Func1) static inline void singleShot(Duration interval, Qt::TimerType timerType, const typename QtPrivate::FunctionPointer<Func1>::Object *receiver, ^ C:\Qt\5.11.1\mingw53_32\include\QtCore/qtimer.h:107:24: note: template argument deduction/substitution failed: customdelegateoperators.cpp:70:17: note: cannot convert '(const CustomDelegateOperators*)this' (type 'const CustomDelegateOperators*') to type 'Qt::TimerType' }); ^ In file included from C:\Qt\5.11.1\mingw53_32\include\QtCore/QTimer:1:0, from customdelegateoperators.cpp:4: C:\Qt\5.11.1\mingw53_32\include\QtCore/qtimer.h:123:13: note: candidate: template<class Duration, class Func1> static typename std::enable_if<((! QtPrivate::FunctionPointer<Func2>::IsPointerToMemberFunction) && (! std::is_same<const char*, Func1>::value)), void>::type QTimer::singleShot(Duration, Func1) singleShot(Duration interval, Func1 slot) ^ C:\Qt\5.11.1\mingw53_32\include\QtCore/qtimer.h:123:13: note: template argument deduction/substitution failed: customdelegateoperators.cpp:70:17: note: candidate expects 2 arguments, 3 provided }); ^ In file included from C:\Qt\5.11.1\mingw53_32\include\QtCore/QTimer:1:0, from customdelegateoperators.cpp:4: C:\Qt\5.11.1\mingw53_32\include\QtCore/qtimer.h:130:13: note: candidate: template<class Duration, class Func1> static typename std::enable_if<((! QtPrivate::FunctionPointer<Func2>::IsPointerToMemberFunction) && (! std::is_same<const char*, Func1>::value)), void>::type QTimer::singleShot(Duration, Qt::TimerType, Func1) singleShot(Duration interval, Qt::TimerType timerType, Func1 slot) ^ C:\Qt\5.11.1\mingw53_32\include\QtCore/qtimer.h:130:13: note: template argument deduction/substitution failed: customdelegateoperators.cpp:70:17: note: cannot convert '(const CustomDelegateOperators*)this' (type 'const CustomDelegateOperators*') to type 'Qt::TimerType' }); ^ In file included from C:\Qt\5.11.1\mingw53_32\include\QtCore/QTimer:1:0, from customdelegateoperators.cpp:4: C:\Qt\5.11.1\mingw53_32\include\QtCore/qtimer.h:138:13: note: candidate: template<class Duration, class Func1> static typename std::enable_if<((! QtPrivate::FunctionPointer<Func2>::IsPointerToMemberFunction) && (! std::is_same<const char*, Func1>::value)), void>::type QTimer::singleShot(Duration, QObject*, Func1) singleShot(Duration interval, QObject *context, Func1 slot) ^ C:\Qt\5.11.1\mingw53_32\include\QtCore/qtimer.h:138:13: note: template argument deduction/substitution failed: customdelegateoperators.cpp:70:17: note: cannot convert '(const CustomDelegateOperators*)this' (type 'const CustomDelegateOperators*') to type 'QObject*' }); ^ In file included from C:\Qt\5.11.1\mingw53_32\include\QtCore/QTimer:1:0, from customdelegateoperators.cpp:4: C:\Qt\5.11.1\mingw53_32\include\QtCore/qtimer.h:145:13: note: candidate: template<class Duration, class Func1> static typename std::enable_if<((! QtPrivate::FunctionPointer<Func2>::IsPointerToMemberFunction) && (! std::is_same<const char*, Func1>::value)), void>::type QTimer::singleShot(Duration, Qt::TimerType, QObject*, Func1) singleShot(Duration interval, Qt::TimerType timerType, QObject *context, Func1 slot) ^ C:\Qt\5.11.1\mingw53_32\include\QtCore/qtimer.h:145:13: note: template argument deduction/substitution failed: customdelegateoperators.cpp:70:17: note: cannot convert '(const CustomDelegateOperators*)this' (type 'const CustomDelegateOperators*') to type 'Qt::TimerType' }); ^ In file included from C:\Qt\5.11.1\mingw53_32\include\QtCore/QTimer:1:0, from customdelegateoperators.cpp:4: C:\Qt\5.11.1\mingw53_32\include\QtCore/qtimer.h:183:17: note: candidate: static void QTimer::singleShot(std::chrono::milliseconds, const QObject*, const char*) static void singleShot(std::chrono::milliseconds value, const QObject *receiver, const char *member) ^ C:\Qt\5.11.1\mingw53_32\include\QtCore/qtimer.h:183:17: note: no known conversion for argument 1 from 'int' to 'std::chrono::milliseconds {aka std::chrono::duration<long long int, std::ratio<1ll, 1000ll> >}' C:\Qt\5.11.1\mingw53_32\include\QtCore/qtimer.h:188:17: note: candidate: static void QTimer::singleShot(std::chrono::milliseconds, Qt::TimerType, const QObject*, const char*) static void singleShot(std::chrono::milliseconds value, Qt::TimerType timerType, const QObject *receiver, const char *member) ^ C:\Qt\5.11.1\mingw53_32\include\QtCore/qtimer.h:188:17: note: candidate expects 4 arguments, 3 provided Makefile.Debug:10067: recipe for target 'debug/customdelegateoperators.o' failed
By the way I set
CONFIG += c++11
in the project file. -
Remove
CustomDelegateOperators::
before the signal name. -
wrote on 22 Jan 2019, 20:16 last edited by
@SGaist said in QTimer with lambda functions:
Remove
CustomDelegateOperators::
before the signal name.Unfortunately the error messages are still there:
error: 'this' was not captured for this lambda function
else QTimer::singleShot(10, this, [idx] () { emit validationFailed(idx); });
^
error: cannot call member function 'void CustomDelegateOperators::validationFailed(QModelIndex) const' without object
error: no matching function for call to 'QTimer::singleShot(int, const CustomDelegateOperators*, CustomDelegateOperators::setModelData(QWidget*, QAbstractItemModel*, const QModelIndex&) const::<lambda()>)'
else QTimer::singleShot(10, this, [idx] () { emit validationFailed(idx); });
^
error: no type named 'Object' in 'struct QtPrivate::FunctionPointer<CustomDelegateOperators::setModelData(QWidget*, QAbstractItemModel*, const QModelIndex&) const::<lambda()> >'
error: no matching function for call to 'singleShot' -
@SGaist said in QTimer with lambda functions:
Remove
CustomDelegateOperators::
before the signal name.Unfortunately the error messages are still there:
error: 'this' was not captured for this lambda function
else QTimer::singleShot(10, this, [idx] () { emit validationFailed(idx); });
^
error: cannot call member function 'void CustomDelegateOperators::validationFailed(QModelIndex) const' without object
error: no matching function for call to 'QTimer::singleShot(int, const CustomDelegateOperators*, CustomDelegateOperators::setModelData(QWidget*, QAbstractItemModel*, const QModelIndex&) const::<lambda()>)'
else QTimer::singleShot(10, this, [idx] () { emit validationFailed(idx); });
^
error: no type named 'Object' in 'struct QtPrivate::FunctionPointer<CustomDelegateOperators::setModelData(QWidget*, QAbstractItemModel*, const QModelIndex&) const::<lambda()> >'
error: no matching function for call to 'singleShot'@Mark81
Hi
I had to capture this in the [] for it to know the signal.QTimer::singleShot(10, this, [this, idx] () { emit validationFailed(idx); });
notice the extra this in the [] besides idx
-
wrote on 22 Jan 2019, 20:25 last edited by
-
Hi
Hmm, it does look correct.
Can you try without the first "this" (the context)QTimer::singleShot(10,[this, idx] () { emit validationFailed(idx); });
and if that still complains, try a dummy to see if something with the surrounding code. like being in a switch.
QTimer::singleShot(10,[] () { });
if it complains about this too, its something else.
it seems to complain about CustomDelegateOperators cant be converted to a QObject which is odd as
QStyledItemDelegate is. -
On side note, I would rather using something like:
QMetaObject::invokeMethod(this, "validationFailed", Qt::QueuedConnection, Q_ARG(QModelIndex, idx));
-
Hi
Hmm, it does look correct.
Can you try without the first "this" (the context)QTimer::singleShot(10,[this, idx] () { emit validationFailed(idx); });
and if that still complains, try a dummy to see if something with the surrounding code. like being in a switch.
QTimer::singleShot(10,[] () { });
if it complains about this too, its something else.
it seems to complain about CustomDelegateOperators cant be converted to a QObject which is odd as
QStyledItemDelegate is.wrote on 22 Jan 2019, 20:36 last edited by@mrjj said in QTimer with lambda functions:
Can you try without the first "this" (the context)
HERE WE GO!!!!
This works!
But I'm honestly astonished about all these attempts! Please, don't misunderstand. I'm very grateful to you and all other guys, but I don't understand why there is so much confusion about the syntax! -
On side note, I would rather using something like:
QMetaObject::invokeMethod(this, "validationFailed", Qt::QueuedConnection, Q_ARG(QModelIndex, idx));
wrote on 22 Jan 2019, 20:39 last edited by@SGaist said in QTimer with lambda functions:
On side note, I would rather using something like:
QMetaObject::invokeMethod(this, "validationFailed", Qt::QueuedConnection, Q_ARG(QModelIndex, idx));
Thanks but this doesn't compile LOL!
I'm going to stay with the other solution that apparently "fix" also the problem of the validation. -
Out of curiosity, what errors are you getting ?
-
wrote on 23 Jan 2019, 08:22 last edited by
-
wrote on 23 Jan 2019, 08:55 last edited by JonB
@Mark81
I'm not a C++er, but since the only argument of typeQObject*
you are passing is yourthis
as the first parameter, I assume it must be that yourthis
is currentlyconst
and causes the error. You must be inside a function which is itself declaredconst
, and hencethis
isconst
and unacceptable toQMetaObject::invokeMethod()
?You commented earlier that you found lambda syntax confusing, with which I whole-heartedly agree. They are a syntactic mess in many languages, especially C++ IMHO. I don't know, but you/others might like to peruse the little article https://medium.com/genymobile/how-c-lambda-expressions-can-improve-your-qt-code-8cd524f4ed9f I came across; whoever it's written by, it lays things out in a nice, big font!
-
@mrjj said in QTimer with lambda functions:
Can you try without the first "this" (the context)
HERE WE GO!!!!
This works!
But I'm honestly astonished about all these attempts! Please, don't misunderstand. I'm very grateful to you and all other guys, but I don't understand why there is so much confusion about the syntax!wrote on 23 Jan 2019, 11:01 last edited by@Mark81 said in QTimer with lambda functions:
but I don't understand why there is so much confusion about the syntax!
The problem is that
this
isconst
insidesetModelData
. Not something easy to see. Exactly the same reason whyQMetaObject::invokeMethod
doesn't work.I'm surprised the lambda version works without declaring the signal as
const
-
@Mark81 said in QTimer with lambda functions:
but I don't understand why there is so much confusion about the syntax!
The problem is that
this
isconst
insidesetModelData
. Not something easy to see. Exactly the same reason whyQMetaObject::invokeMethod
doesn't work.I'm surprised the lambda version works without declaring the signal as
const
wrote on 23 Jan 2019, 12:43 last edited by@VRonin said in QTimer with lambda functions:
I'm surprised the lambda version works without declaring the signal as
const
As you can see in the first post the signal is actually const:
signals: void validationFailed(QModelIndex index) const;
1/18