In Qt how to connect a singleton instance to a slot? - c++

I'm programming in Qt Creator and encountered a problem. I made a singleton class, and I'm trying to connect it to a slot in the widget, but it doesn't take the pointer that returns
from Singleton::getInstance() as the same instance that emits the signal.
My code is as follows:
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private slots:
void setString(int var);
}
Implementation:
connect(Singleton::getInstance(),SIGNAL(changeString(int)),this,SLOT(setString(int)));
Signal in the singleton class:
signals:
void changeString(int var);
the call to the signal in the singleton class:
emit(Singleton::getInstance()->changeString(5));
Nothing happens when signal emits. The debugger doesn't enter the slot.

Most probably it's the differing method signature of the slot - setString(IMSS_Status); vs. setString(int);
Also, in case of a custom type, you should call
qRegisterMetaType<IMSS_Status>("IMSS_Status");
to register it correctly with the meta type system. Otherwise, queued slot executions won't work, for instance.

Your problem may be caused by signature of the methods. Before you make connect signal with slot u should define your signal to system by using qRegisterMetaType<Your Class >("Class Definition name");
And is the signal of changeString signature ? "void changeString(int)"
i had encountered your problem and i solved my problem by making qRegisterMetaType and controlling signatures.

Does the Singleton class have the Q_OBJECT macro also? I don't know if it needs it also or not.

I would lean towards emit(Singleton::getInstance()->changeString(5)); not being correct.
emit should be called from inside a Singleton function as follows:
emit(changeString(5));
I'm surprised the code you posted compiles and runs without warning, I would have expected a runtime error about the signal not existing.

Related

Cannot connect signal from an outer shared library to overloaded slot of QWidget derived class

I try to connect the signal from an outer shared library to an overloaded slot of base QWidget class's slot.
Suppose this is an instance of a class derived from QWidget
class MyClass : public QWidget;
...
MyClass* this_instance = new MyClass;
I tried the following approach
connect(obj_from_sl, SIGNAL(signalFromSL()), this, SLOT(update());
// update() is QWidget's slot
// the "sl" suffixs stands for "shared library"
but it didn't work. I have got linker errors. I have searched and found out, that
it is impossible to connect signal from an outer shared library using SIGNAL/ SLOT macros inside the connect function. It might be possible if I use function pointers.
OK. Let's change the signature:
connect(obj_from_sl, &ClassFromSL::signalFromSL, this, &QWidget::update);
^ error comes here
and voilĂ 
cannot determine which instance of an overloaded function "QWidget::update" is intended.
Could anyone help me to solve this problem?
The QWidget::update() function has different arguments, so it requires explicit casting for the new signal/slot syntax use
connect(obj_from_sl, &ClassFromSL::signalFromSL, this, static_cast<void (QWidget::*) )>(&QWidget::update));

Is Q_INVOKABLE needed to invoke a public QObject function from QML at all in Qt5?

I just realized that I can call pretty much any function of an object that is exposed to QML. Now I am curious about Q_INVOKABLE. The Qt5 docs state:
[...] any QML code can access the following members of an
instance of a QObject-derived class:
Properties
Methods (providing they are public slots or flagged with
Q_INVOKABLE)
Signals
Since Qt5 (In C++) I can invoke any public function of a QObject like a slot, i.e. I do not have to declare them as 'public slot'. Does this mean I can call any method from QML? I cant find anything in the docs.
Yes, you have to mark your function of a QObject with Q_INVOKABLE unless it's a public slot in order to be able to call it from QML.
Both Q_INVOKABLE and the slots keyword register your function with Qt meta-system. The difference is that with Q_INVOKABLE you can return values.

Connecting to a base class' signal when overriding it in a subclass

Qt provides the QSpinBox, which is some far QObject derivative that provides a signal:
class QSpinBox:
public /* ... */ QObject {
signals:
void valueChanged(int i);
};
When deriving from this spin box, I might provide an override for this signal to emit some beautified version of the value:
class MySpinBox:
public QSpinBox {
private slots:
void originalValueChanged(int i) {
/* Beautify */
emit valueChanged( 42 * i );
}
signals:
void valueChanged(int myPersonalI);
};
This seems perfectly fine: The signal MySpinBox::valueChanged(int) hides the inherited signal. The only bit missing is to connect the inherited QSpinBox::valueChanged(int) to the private slot MySpinBox::originalValueChanged(int).
While this is possible using the new signals and slot syntax:
connect(
static_cast<QSpinBox *>(this), &QSpinBox::valueChanged,
this, &MySpinBox::originalValueChanged);
I am neither sure if this is allowed or sensible, nor how to connect the signal using the conventional string based signal/slot syntax. Using the latter, the slot is obviously connected to the MySpinBox::originalValueChanged(int) signal, which is clearly not intended.
Purpose
The above example is reduced to the problem I think I face. To understand why I ran into the problem and maybe to guide me out of this (pretended) broken design, think of a QDoubleSpinBox derivative to enter some physical quantitiy, e.g. speed. The user may want to enter this in some preferred unit, which may be km/h or mph. To get the unit conversion logic out of the application, I composed a new widget, derived from QWidget and containing only a QDoubleSpinBox. Then I implemented the usual spin box methods (setMinimum, setSingleStep etc.) that take the respective properties in SI dimension (i.e., m/s in this example), convert them to some chosen unit and then configure the inferior double spin box.
A setValue(double) converts its argument to the user's unit and passes it on to the inferior. In turn, there is a valueChanged(double) signal that is emitted whenever the inferior spin box emits valueChanged, but with the quantity converted back to the SI dimension.
So in the end I was tinkering about not composing a QWidget derivative with an inferior spin box but to derive from the QDoubleSpinBox and reimplement.
Pros and cons appear partly clear, including the issue explained by #Pavel Strakhov below already. Composing the widget in fact gets me rid of wrongly inherited methods being called (due to not being virtual), at the cost of a wrapping QWidget. So as an intermediate step, I'm tinkering of deriving private from QDoubleSpinBox. This is surely not a matter of resources in a GUI application, but to me it's also a matter of learning and tinkering.
Then I stumbled about the signal and wondered what Qt might think about it.
Note that QSpinBox::valueChanged is not virtual, meaning that if one have an instance of MySpinBox stored in QSpinBox* pointer and calls its valueChanged method, QSpinBox::valueChanged will be executed instead of MySpinBox::valueChanged. And Qt internal functions will definitely have QSpinBox* pointer to the instance. This inconsistency can be a source of errors. Non-virtual functions are not meant to be redefined in subclasses, and you should not do that. Neither of Qt built-in classes uses such redefinition. Subclasses usually add new signals leaving base class signals untouched.

Qt: Using signals and slots between two child threads

I'm new to Qt, and C++ in general, and I'm trying to make a program that runs two child threads, threadA and threadB. Both threads are created in main.cpp like so:
ThreadA threadA;
threadA.start();
ThreadB threadB;
threadB.start();
The two threads then run independently.
I need to make threadA able to call a method in threadB, passing data as an argument in the process. I have tried using signals and slots, by adding this to my main.cpp:
QThread::connect(&threadA, SIGNAL(mySignal(uint)),
&threadB, SLOT(mySlot(uint)));
Where threadA::mySignal(uint) is used in a:
//a.h
signals:
void mySignal(unsigned int blah);
//a.cpp
emit mySignal(42);
And threadB::mySlot(uint) is in b:
//b.h
public slots:
void mySlot(unsigned int fluff);
//b.cpp
void threadB::mySlot(unsigned int fluff)
{ doStuff(fluff); ... }
The program compiles and runs sucessfully, but I get a message from QObject in my debug log:
QObject::connect: No such slot QThread::mySlot(uint) in ../Project/main.cpp:42
Meaning that the compiler is looking in QThread instead of threadB for mySlot.
Can anyone tell me where I'm going wrong here? Any help would be gratly appreciated, and I can provide more details if nessesary.
First of all for the error you mentioned
The program compiles and runs sucessfully, but I get a message from
QObject in my debug log:
QObject::connect: No such slot QThread::mySlot(uint) in
../Project/main.cpp:42
You are using mySlot and have defined MySlot please refer back your code
You have written
QThread::connect(&threadA, SIGNAL(mySignal(uint)),
&threadB, SLOT(mySlot(uint)));
and defined
//b.h
public slots:
void MySlot(unsigned int fluff);
You are probably missing the Q_OBJECT macro in your threadb.h (and possibly threada.h).
class ThreadB : public QObject
{
Q_OBJECT
...
From the docs:
All classes that contain signals or slots must mention Q_OBJECT at the top of their declaration. They must also derive (directly or indirectly) from QObject.
I'm also assuming that you have subclassed QThread. You should know that QThread is used for managing threads, not processing data. You should subclass QObject instead. Read this for more info about that.

Can Qt signals be public or private?

Can Qt signals be public or private? Can I create internal signals, which are seen only inside the class?
Update: I have a class with some internal signals. How can I make those signals invisible for other classes (encapsulation & information hiding)?
No. Signals cannot be public or private. Qt signals are protected class methods.
"signals" keyword is defined in qobjectdefs.h (line 69 as for Qt 4.6.1):
# define signals protected
UPDATE: signals are only protected upto and including all minor versions of Qt 4. From Qt 5.0 onwards they are public. See https://stackoverflow.com/a/19130831.
A common way, e.g. seen in kdelibs, is this:
Q_SIGNALS:
#ifndef Q_MOC_RUN
private: // don't tell moc, doxygen or kdevelop, but those signals are in fact private
#endif
void somePrivateSignal();
This makes the signal private, i.e. it can only be emitted by the class itself but not by its subclasses. To not make the "private:" overrule Q_SIGNALS (moc wouldn't see somePrivateSignal as signal then), it's inside Q_MOC_RUN, which is only defined when moc runs.
Edit: This approach doesn't work for the new-style connects introduced with Qt 5 (connect(a, &A::someSignal, b, &B::someSlot)), as they require the signal to be accessible.
Signals was protected in Qt4, in Qt5 they are public. Int Qt5 you can make them private by adding QPrivateSignal as the last argument. More on this: http://woboq.com/blog/how-qt-signals-slots-work-part2-qt5.html
Slots are simple methods which can be public, protected, or private.
As Andrei pointed it out, signal are only a redefinition of protected, meaning they can only be emitted by the class in which they are defined.
If you want to make a class emit a signal from anoter one, you have to add it a public method (or slot) like this one:
void emitTheSignal(...) {
emit theSignal(...);
}
Qt signals are public in the sense that any object can connect to any signal.
All the existing answers are incorrect.
A signal can be made private by adding a QPrivateSignal type to its definition as the last argument:
signals:
void mySignal(QPrivateSignal);
QPrivateSignal is a private struct created in each QObject subclass by the Q_OBJECT macro, so you can only create QPrivateSignal objects in the current class.
Technically, the signal still has public visibility, but it can only be emitted by the class that created it.
Nowadays you can use Q_SIGNAL macro and normal C++ access specifier:
protected:
Q_SIGNAL void myProtectedSignal();
private:
Q_SIGNAL void myPrivateSignal();
You can use the PIMPL pattern for that. Your private signals exists in the private implementation only.