Can signals be parameters in Qt? - qt

A function: void function(ObjectName obj, Signal), ObjectName is a class type and obj is an instance. The question is that can the second parameter be a signal which defined in class ObjectName. That means can I use the signal as a normal member function pointer?

Of course! Think about it -- QObject::connect() is a function that takes both signals and slots as parameters. Check out its documentation for the various ways this can be implemented.

Related

How to resolve the ambiguity of the function in qt slot

I want to connect a function to a slot and this is my code.
I get error that no instance of overloaded function matched the argument list.
connect(lineEditCommandInterface, &QLineEdit::textChanged, this, &SUMMIT::ReceiveCommand);
the issue is that ReceiveCommand is a overloaded function and i want to use the function with no arguments.
void ReceiveCommand();
void ReceiveCommand( std::string stdstrCommand);
One possible solution is to use a lambda function:
connect(lineEditCommandInterface, &QLineEdit::textChanged, [this](){
ReceiveCommand();
});
Aanother option could be static casting the slot, just in case you may skip the lambda....
slots:
void fooSlot(int x);
void fooSlot(const QString& n);
then
connect(someObject, &SomeClass::someSignal, this, static_cast<void(MainWindow::*)(const QString&)>(&MainWindow::fooSlot));
connect(someObject, &SomeClass::someSignal, this, static_cast<void(MainWindow::*)(int)>(&MainWindow::fooSlot));
Since Qt 5.6, the recommended (or at least less verbose) way to connect to overloaded signals/slots is with QOverload::of() (which isn't well documented). With Qt 5.7+ and C++14 one can also use qOverload() and friends. Though this doesn't help with mismatched signal/slot parameters, it seems worth pointing out.
Example with C++11 and QOverload:
connect(object, &SomeClass::someSignal, this, QOverload<void>::of(&SUMMIT::ReceiveCommand));
The various options are documented with examples (including the old static_cast method) in: Selecting Overloaded Signals and Slots
Also of possible interest in regards to this question is the section in the same doc: Using Default Parameters in Slots to Connect to Signals with Fewer Parameters. The lambda option is also documented higher up on that page.
Further examples of using QOverload can be found in Qt docs for just about every overloaded signal, (eg. SpinBox::valueChanged()) but it also works for slots.

QMetaObject::invokeMethod alternative with compile-time checking

Besides QMetaObject::invokeMethod is there any type-safe way of invoking a method/slot asynchronously (a.k.a queuing its execution in the GUI thread)?
The QMetaObject::invokeMethod doesn't have compile-time checking for function names. There is also an overhead in specifying the member function by a string since a lookup and string matching is performed for every call.
I wonder if there is anything similar to the new QObject::connect syntax for invoking a method that provides compile time checking.
One solution is using the signal-slot architecture, but this enforces wrapping each caller code in a QObject class to be able to emit that signal.
It is possible to use the QTimer::singleShot for this purpose
QTimer::singleShot(0, object, &Object::method...);
--
QTimer::singleShot(0, object, [object](){
object->method(arg1, arg2, ...);
});
Note: The thread in which QTimer::singleShot is invoked must have an QEventLoop.
Please see this https://doc.qt.io/qt-5/qmetaobject.html#invokeMethod-4
template <typename Functor, typename FunctorReturnType> bool QMetaObject::invokeMethod(QObject *context, Functor function, FunctorReturnType *ret)
This is an overloaded function.
Invokes the function in the event loop of context using the connection type Qt::AutoConnection. function can be a functor or a pointer to a member function. Returns true if the function could be invoked. Returns false if there is no such member or the parameters did not match. The return value of the function call is placed in ret.
Note: This function is thread-safe.
This function was introduced in Qt 5.10.

Why do qobject_cast and dynamic_cast fail in a slot connected to QWidget::destroyed?

I have a class Subclass, subclassed from QObject. I want to know when the item is deleted, so I connected this slot to the QWidget::destroyed() signal inherited by Subclass. But when I try to cast the argument to with qobject_cast, I get a zero result. The same result obtains from C++'s dynamic_cast. Why?
void MyClass::mySlot( QObject * item )
{
qobject_cast<Subclass*>(item); // returns zero, even though item is a Subclass*
}
The reason is that by the time QObject::destroyed() is emitted, your derived class Subclass has already been destroyed. This is implied by the C++ order of destruction. Also, this question deals with a similar issue.
To get around this, you could either use C-style pointer casting (which is dispreferred), or rewrite your code to use a QObject instead.

Can I pass an argument to the slot function when using QObject::connect?

Qt4.8.5
QObject::connect(button,SIGNAL(clicked()),label,SLOT(setText("dd"));
The Qt Creator tell me It's wrong . What's the problem ?
That you can't pass arguments in a connect() statement. You need a "trampoline" slot that sets the text of your label (or, in Qt 5, you might choose to use a lambda).
For instance, by using a subclass:
class MyLabel : public QLabel {
Q_OBJECT
public slots:
void setTextToFoo() { setText("foo"); }
};
// ...
connect(button,SIGNAL(clicked()),label,SLOT(setTextToFoo());
It depends what exactly you are trying to achieve, to be honest, the example code you provided is not very functional, is "dd" a particular static value you are using, or potentially some other string? Where does it come from, is it in the scope of the called, or is it sent by the caller, which is the usual practice when sending arguments to slots.
Either way, in order to make a connect statement the first requirement is for the arguments to match, clicked() has no arguments while setText() has one, so there is a mismatch. As of how to resolve that mismatch, the easiest way is to use simple wrappers, although you can use a QSignalMapper and as of Qt5, lambdas and std::bind.
For starters, you cannot specify the actual argument instance in the connect statement, even with arguments on both sides you only need to specify the types to help resolve overloads (it is terrible with the new connection syntax in Qt5), and not any actual identifiers or literals.
In case of the more usual scenario, where the data is send to the slot by the caller, the identifier or literal is specified in the emit signal(value) statement. Since you don't have clicked(const QString &) you need a wrapper slot that you connect to clicked() and emit with the value in that wrapper slot, or subclass the button and add your own overload of clicked(QString).
In case the value is in the scope of the called, then subclassing doesn't make much sense, all you need is the wrapper slot in the scope of the called object.
If you want more, you will have to use Qt 5, whose syntax is significantly more powerful.
If the question is whats wrong, just remember the parameter number must be the same for the Signal and the Slot. Asking a collegue and according the Peppe, setText(QString) wait for One parameter and the Clicked() is empty...A custom slot is to call the setText() method indirectly.
You can look that : http://qt-project.org/doc/qt-4.8/widgets-calculator.html
It uses the QWidget, an important part of Qt interfaces beside QML.

How does Qt implement signals and slots?

Can someone explain to me the basic idea of Qt signals&slots mechanism IMPLEMENTATION?
I want to know what all those Q_OBJECT macros do "in plain C++".
This question is NOT about signals&slots usage.
added:
I know that Qt uses moc compiler to transform Qt-C++ in plain C++.
But what does moc do?
I tried to read "moc_filename.cpp" files but I have no idea what can something like this mean
void *Widget::qt_metacast(const char *_clname)
{
if (!_clname) return 0;
if (!strcmp(_clname, qt_meta_stringdata_Widget))
return static_cast<void*>(const_cast< Widget*>(this));
return QDialog::qt_metacast(_clname);
}
Concerning the signals and slots, the Q_OBJECT macro adds a virtual function qt_metacall() declaration into the class’s declaration which is to be defined later by the the moc. (It also adds some declarations for conversion but that’s not too important here.)
The moc then reads the header file and when it sees the macro, it generates another .cpp file named moc_headerfilename.cpp with the definitions to the virtual functions and – you might have asked yourself why you can get away with mentioning the signals: in your header file without a proper definition – of the signals.
So, when a signal is called, the definition from the mocfile is executed and QMetaObject::activate() is called with the signal’s name and the signal’s arguments.
The activate() function then figures out which connections have been established and fetches the names for the appropriate slots.
Then it calls qt_metacall with the slot names and the arguments given to the signal and the metacall function delegates this with the help of a large switch—case statement to the real slots.
As there is no real runtime information possible in C++ concerning the actual names for the signals and slots, as has already been noticed, these will be encoded by the SIGNAL and SLOT macros to simple const char*s (with either "1" or "2" added to the name to distinguish signals from slots).
As is defined in qobjectdefs.h:
#define SLOT(a) "1"#a
#define SIGNAL(a) "2"#a
—
The other thing the Q_OBJECT macro does is defining the tr() functions inside your object which can be used to translate your application.
Edit
As you asked what the qt_metacast is doing. It checks whether an object belongs to certain class and if it does returns the pointer to it. If it doesn’t, it returns 0.
Widget* w = new Widget();
Q_ASSERT(w->qt_metacast("Widget") != 0);
Q_ASSERT(w->qt_metacast("QWidget") != 0);
Q_ASSERT(w->qt_metacast("QObject") != 0);
Q_ASSERT(w->qt_metacast("UnrelatedClass") == 0);
This is needed to provide some runtime reflection which is not possible otherwise. The function is called in QObject::inherits(const char *) for example and simply checks for inheritance.
Those macros do absolutely nothing "in plain C++", - they expand to empty strings (I think).
QT uses a meta-object compiler, that generates C++ code for Q_OBJECT-enabled classes (implementing the signals/slots you define, among other things).
You can read more about it in the official documentation.
The basic idea is that you can connect your objects allowing them to execute a method (slot) when a signal is done.
connect(pistol,SIGNAL(sigShoot()),runner,SLOT(slotRun()))
Doing the connection above, when the pistol emits the signal, the runner will execute its slot.
To do this, you have to declare your signals and slots in your respective classes.
Is the basic idea.
Good luck!

Resources