QT Widget Slot Call Not Activated by Separate Thread Signal - c++

I have 5 classes that interact (maintaining professionally, not author). My problem is that the code that is emitting the signal (there is just one, code below) is never activating the slot (MyWidget::HandleMeasurementChanged). This system has a large degree of complexity. I have tried to reduce that, but think the complexity likely contributes to the problem. There is also a high rate of calls to Observer::notify, but most of these will get filtered out by code that I have not posted here and the Emit calls are fairly rare. If anyone could help point me to why the slot is not getting activated, I'd really appreciate it. It is almost acting like the MyWidget class instance is not processing its event loop. I have had a little success setting the connect type to Direct Connection, but since the emit is in a separate thread and the production code for the slot will update the UI I have ruled that out as a final solution.
class IObserver { public: virtual void notify()=0; };
class ExternalMeasurement { ... };
class Measurement { public: Measurement(ExternalMeasurement source); };
class Observer : public QThread, public IObserver
{
signals:
void MeasurementChanged(boost::shared_ptr<Measurement> measurement);
public:
//called by 3rd party in separate thread
virtual void notify(ExternalMeasurement measurement)
{
_measurement_ =
boost::shared_ptr<Measurement>(new Measurement(measurement));
emit MeasurementChanged(_measurement);
}
private:
boost::shared_ptr<Measurement> _measurement_;
};
class MyWidget : public QWidget
{
private:
Component _component_;
public slots:
void HandleMeasurementChanged(boost::shared_ptr<Measurement> measurement);
public:
MyWidget(Component * component_)
};
MyWidget::MyWidget(Component * component_)
{
_component_ = component_;
connect(
_component_->_observer_,
MeasurementChanged(boost::shared_ptr<Measurement> measurement),
this,
HandleMeasurementChanged(boost::shared_ptr<Measurement> measurement));
}
class Component
{
private:
QApplication * _application_;
MyWidget * _widget_;
Observer * _observer_;
public:
void MainFunc();
}
void Component::MainFunc()
{
_observer_ = new Observer();
...
_application_ = new QApplication(...);
...
_widget_ = new MyWidget(...);
...
_widget_->show();
_application_->exec();
}

This was referenced in the link that Jeremy added in a comment to my question, but just for clarity:
The solution was to add:
qRegisterMetaType<shared_ptr<Measurement> >("shared_ptr<Measurement>");
immediately before the call to connect.

Related

Performance degrade from using QThread and multiple signals-and-slots connections

I am having trouble trying to figure out where this performance degrade in my codes comes from. My program is quite big so I'll simplify using some examples. Say I have a MainUI class subclassed from QMainWindow, which has two member objects, a Worker (subclassed from QThread) and a DisplayPanel (subclassed from QGLWidget). Then a connection is established between a signal from this Worker object (emitted from its run method) and a slot in the DisplayPanel object. And I see performance degrade in the run method if I increase the number of connections.
Basically what I am describing is (very simplified):
class Worker : public QThread {
Q_OBJECT
signals:
void updateDisplay();
protected:
void startWorking() {
// some setup codes
this->start();
}
void run() {
while (1) {
// some processing codes
emit updateDisplay();
}
}
};
class DisplayPanel : public QOpenGLWidget, protected QOpenGLFunctions_5_0_Core {
Q_OBJECT
public slots:
void refresh() {
update();
}
};
class MainUI : public QMainWindow {
Q_OBJECT
public:
explicit MainUI(QWidget *parent = 0) {
// some Ui setup codes
worker = new Worker();
num_panels = 5 // arbitrary number
panels.resize(num_panels);
for (auto p : panels) {
p = new DisplayPanel();
connect(worker, SIGNAL(updateDisplay()), p, SLOT(refresh()));
}
}
void process() {
worker->startWorking();
}
private:
unsigned num_panels;
Worker* worker;
std::vector<DisplayPanel*> panels;
};
Imagine MainUI::process() was called from the GUI.
What confuses me is that there is some noticeable performance degrade in the while loop of Worker::run() if I increase MainUI::num_panels. From my understanding, the increased number of signals-and-slots connections should not affect the performance of Worker very much because the queued requests to DisplayPanel::update() should run on a different thread.
Any insights would be appreciated!

Deciding between signal-slot mechanism versus traditional loop

I want to update many objects. I have the option to do so with traditional loop like:
void ParentClass::updateItems(const float factor)
{
for (Item *item : items()) {
item->update(factor)
}
}
... or I can do it with signal-slot mechanism like:
class ParentClass : public QObject
{
Q_OBJECT
Q_SIGNALS:
// The signal which will be emitted by parent:
void updateNeeded(const float factor);
private:
void updateItems(const float factor);
}
// Signal is emitted here
void ParentClass::updateItems(const float factor)
{
emit updateNeeded(factor);
}
class Item : public QObject
{
Q_OBJECT
Item(ParentClass *parent) : QObject()
, m_parent(parent)
{
// Connect parent signal to each item slot at each item constructor
QObject::connect(m_parent, &ParentClass::UpdateNeeded,
this, &Item::handleUpdate);
}
public Q_SLOTS:
void handleUpdate(const float factor);
private:
ParentClass *m_parent;
}
// The slot which handles emitted signal:
void Item::handleUpdate(const float factor)
{
this->update(factor);
}
I have tested the loop approach and it works.
I'm thinking on signal-slot mechanism, maybe it has some benefits for complex code.
I wonder which approach is how it should be done or is there a better way?
After writing my question, I found this post which is really helpful but I"m not sure if it is directly related to my question.
Use the loop based approach whenever and whereever you can, KISS
signal-slot is a very loose-coupled method of interfacing - while this can be great sometimes (mostly when other options are not possible..) it is much more brittle than regular function calls.

Qt with QAMQP / RabbitMQ

I’m using this connector to RabbitMQ:
https://github.com/fuCtor/QAMQP
I need performance and multi-thread in my application. Please, can I use multi-thread with this connector?
I tried:
void Test::newMessage(QAMQP::Queue * q) {
while (q->hasMessage()) {
QAMQP::MessagePtr message = q->getMessage();
MyEvent *me = new MyEvent();
me->message = message;
poolThreadPosicao->start(me);
}
}
class MyEvent : public QRunnable {
public:
QAMQP::MessagePtr message;
void run() {
s.queue->ack(this->message);
}
};
In some messages the RabbitMQ say: “Unacked 10 messages”. The 10 messages is my qos in broker message. What I need solve this? How to do?
First of all I recommend that you switch to https://github.com/mbroadst/qamqp, as it is the replacement for the original project (which is no longer in active development). The updated code contains many performance and memory enhancements, as well as more complete support for RabbitMQ. Having said that, currently both versions of the project are aimed at having one connection per thread. This means that any of the Channels that you create (an Exchange, or a Queue), will be parented to the connection (Client) which created it and therefore are bound to the creating thread.
One way to handle the problem you are facing would be to inherit from QRunnable and QObject, emitting the message when you have completed your task (NOTE: this is untested, I'm just giving the basic structure):
using namespace QAMQP;
class MessageJob : public QRunnable, public QObject
{
Q_OBJECT
public:
MessageJob(const Message &message)
: m_message(message)
{
}
virtual void run() {
// process the message
// when you are done, emit the finished signal
Q_EMIT finished(m_message);
}
Q_SIGNALS:
void finished(const Message &message);
private:
Message m_message;
};
class Test : public QObject
{
Q_OBJECT
public:
Test(QObject *parent = 0)
: QObject(parent)
{
// setup and connect client
// create queue and start consuming
}
private Q_SLOTS:
void messageReceived(const Message &message)
{
MessageJob *job = new MessageJob; // no parent, this will be autodeleted
connect(job, SIGNAL(finished(Message)), this, SLOT(jobFinished(Message)), Qt::QueuedConnection);
// NOTE: Qt::QueuedConnection is very important as it allows the signal to
// cross threads
QThreadPool::globalInstance()->start(job);
}
void jobFinished(const Message &message) {
m_queue->ack(message);
}
private:
Client m_client;
Queue *m_queue;
};

Qt: How to implement common base-class signal/slot functionality for all widgets and widget types (via a virtual base class slot)?

I would like to derive all of my widgets from a base class widget that automatically establishes a signal/slot connection between a slot for the class and a (rarely called) signal.
The slot is a virtual function, so that any widgets for which I wish to implement custom functionality can derive from the virtual slot function. In the desired scenario, all my widgets would derive from this base class with the virtual slot, so that by default all of my widget instances would be connected to the desired signal with a slot defined for the object (with default behavior from the base class).
I know that virtual slots are allowed in Qt. However, deriving from two QObject classes is not supported, so that, for example, the following code is disallowed:
class MySignaler : public QObject
{
Q_OBJECT
public:
MySignaler : QObject(null_ptr) {}
signals:
void MySignal();
}
MySignaler signaler;
class MyBaseWidget: public QObject
{
Q_OBJECT
public:
MyBaseWidget() : QObject(null_ptr)
{
connect(&signaler, SIGNAL(MySignal()), this, SLOT(MySlot()));
}
public slots:
virtual void MySlot()
{
// Default behavior here
}
}
// Not allowed!
// Cannot derive from two different QObject-derived base classes.
// How to gain functionality of both QTabWidget and the MyBaseWidget base class?
class MyTabWidget : public QTabWidget, public MyBaseWidget
{
Q_OBJECT
public slots:
void MySlot()
{
// Decide to handle the signal for custom behavior
}
}
As the sample code demonstrates, it seems impossible to gain both the benefits of (in this example) the QTabWidget, and also the automatic connection from the desired signal function to the virtual slot function.
Is there some way, in Qt, to have all my application's widget classes share common base-class slot and connect() functionality while allowing my widgets to nonetheless derive from Qt widget classes such as QTabWidget, QMainWindow, etc.?
Sometimes when inheritance is problematic, one can replace it, or a part of it, with composition.
That's the approach needed in Qt 4: instead of deriving from a QObject, derive from a non-QObject class (MyObjectShared) that carries a helper QObject that is used as a proxy to connect the signal to its slot; the helper forwards that call to the non-QObject class.
In Qt 5, it is not necessary to derive from a QObject at all: signals can be connected to arbitrary functors. The MyObjectShared class remains the same.
Should Qt 4 compatibility be generally useful in other areas of the code, one can use a generic connect function that connects signals to functors in both Qt 4 and Qt 5 (in Qt 4, it would use an implicit helper QObject).
// https://github.com/KubaO/stackoverflown/tree/master/questions/main.cpp
#include <QtCore>
#include <functional>
#include <type_traits>
class MySignaler : public QObject {
Q_OBJECT
public:
Q_SIGNAL void mySignal();
} signaler;
#if QT_VERSION < 0x050000
class MyObjectShared;
class MyObjectHelper : public QObject {
Q_OBJECT
MyObjectShared *m_object;
void (MyObjectShared::*m_slot)();
public:
MyObjectHelper(MyObjectShared *object, void (MyObjectShared::*slot)())
: m_object(object), m_slot(slot) {
QObject::connect(&signaler, SIGNAL(mySignal()), this, SLOT(slot()));
}
Q_SLOT void slot() { (m_object->*m_slot)(); }
};
#endif
class MyObjectShared {
Q_DISABLE_COPY(MyObjectShared)
#if QT_VERSION < 0x050000
MyObjectHelper helper;
public:
template <typename Derived>
MyObjectShared(Derived *derived) : helper(derived, &MyObjectShared::mySlot) {}
#else
public:
template <typename Derived, typename = typename std::enable_if<
std::is_base_of<MyObjectShared, Derived>::value>::type>
MyObjectShared(Derived *derived) {
QObject::connect(&signaler, &MySignaler::mySignal,
std::bind(&MyObjectShared::mySlot, derived));
}
#endif
bool baseSlotCalled = false;
virtual void mySlot() { baseSlotCalled = true; }
};
class MyObject : public QObject, public MyObjectShared {
Q_OBJECT
public:
MyObject(QObject *parent = nullptr) : QObject(parent), MyObjectShared(this) {}
// optional, needed only in this immediately derived class if you want the slot to be a
// real slot instrumented by Qt
#ifdef Q_MOC_RUN
void mySlot();
#endif
};
class MyDerived : public MyObject {
public:
bool derivedSlotCalled = false;
void mySlot() override { derivedSlotCalled = true; }
};
void test1() {
MyObject base;
MyDerived derived;
Q_ASSERT(!base.baseSlotCalled);
Q_ASSERT(!derived.baseSlotCalled && !derived.derivedSlotCalled);
signaler.mySignal();
Q_ASSERT(base.baseSlotCalled);
Q_ASSERT(!derived.baseSlotCalled && derived.derivedSlotCalled);
}
int main(int argc, char *argv[]) {
test1();
QCoreApplication app(argc, argv);
test1();
return 0;
}
#include "main.moc"
To share some code between two QObjects, you could have the QObject as a member of the class,an interposing non-object class that uses generic class that's parametrized only on the base type. The generic class can have slots and signals. They must be made visible to moc only in the immediately derived class - and not in any further derived ones.
Alas, you generally cannot connect any of the generic class's signals or slots in the constructor of the class, since at that point the derived class isn't constructed yet, and its metadata isn't available - from Qt's perspective, the signals and slots don't exist as such. So the Qt 4-style runtime-checked connect will fail.
The compile-time-checked connect will not even compile, because the this pointer it works on has an incorrect compile-time type, and you know nothing about the type of the derived class.
A workaround for Qt-4 style connect only is to have a doConnections method that the derived constructor has to call, where the connections are made.
Thus, let's make the generic class parametric on the base and the derived class as well - the latter is known as the Curiously Recurring Template Pattern, or CRTP for short.
Now you have access to the derived class's type, and can use a helper function to convert this to a pointer to the derived class, and use it in the Qt 5-style compile-time-checked connects.
The Qt 4-style runtime checked connect still needs to be invoked from doConnections. So,if you use Qt 5, that's not an issue. You shouldn't be using Qt 4-style connect in Qt 5 code anyway.
The slots require slightly different treatment depending on whether the class immediately derived from the generic class overrides them or not.
If a slot is virtual and has an implementation in the immediately derived class, you should expose it to moc in the normal fashion - using a slots section or the Q_SLOT macro.
If a slot doesn't have an implementation in the immediately derived class (whether virtual or not), its implementation in the generic class should be made visible to moc only, but not to the compiler - you don't wish to override it, after all. Thus the slot declarations are wrapped in #ifdef Q_MOC_RUN block that is only active when moc is reading the code. The generated code will refer to the generic implementations of the slots.
As we wish to make sure this indeed works, we'll add some booleans to track whether the slots were invoked.
// main.cpp
#include <QtWidgets>
template <class Base, class Derived> class MyGenericView : public Base {
inline Derived* dthis() { return static_cast<Derived*>(this); }
public:
bool slot1Invoked, slot2Invoked, baseSlot3Invoked;
MyGenericView(QWidget * parent = 0) : Base(parent),
slot1Invoked(false), slot2Invoked(false), baseSlot3Invoked(false)
{
QObject::connect(dthis(), &Derived::mySignal, dthis(), &Derived::mySlot2); // Qt 5 style
QObject::connect(dthis(), &Derived::mySignal, dthis(), &Derived::mySlot3);
}
void doConnections() {
Q_ASSERT(qobject_cast<Derived*>(this)); // we must be of correct type at this point
QObject::connect(this, SIGNAL(mySignal()), SLOT(mySlot1())); // Qt 4 style
}
void mySlot1() { slot1Invoked = true; }
void mySlot2() { slot2Invoked = true; }
virtual void mySlot3() { baseSlot3Invoked = true; }
void emitMySignal() {
emit dthis()->mySignal();
}
};
The generic class is very simple to use. Remember to wrap any non-virtual overridden slots in a moc-only guard!
Also recall the general rule that applies to all Qt code: if you have a slot, it should be declared to moc only once. So, if you had a class that further derives from MyTreeWidget or MyTableWidget, you don't want a Q_SLOT or slots macro in front of any necessarily virtual slot overrides. If present, it'll subtly break things. But you definitely want Q_DECL_OVERRIDE.
If you're on Qt 4, remember to call doConnections, otherwise the method is unnecessary.
The particular choice of QTreeWidget and QTableWidget is completely arbitrary, meaningless, and shouldn't be taken to mean that such use makes any sense (it likely doesn't).
class MyTreeWidget : public MyGenericView<QTreeWidget, MyTreeWidget> {
Q_OBJECT
public:
bool slot3Invoked;
MyTreeWidget(QWidget * parent = 0) : MyGenericView(parent), slot3Invoked(false) { doConnections(); }
Q_SIGNAL void mySignal();
#ifdef Q_MOC_RUN // for slots not overridden here
Q_SLOT void mySlot1();
Q_SLOT void mySlot2();
#endif
// visible to the C++ compiler since we override it
Q_SLOT void mySlot3() Q_DECL_OVERRIDE { slot3Invoked = true; }
};
class LaterTreeWidget : public MyTreeWidget {
Q_OBJECT
public:
void mySlot3() Q_DECL_OVERRIDE { } // no Q_SLOT macro - it's already a slot!
};
class MyTableWidget : public MyGenericView<QTreeWidget, MyTableWidget> {
Q_OBJECT
public:
MyTableWidget(QWidget * parent = 0) : MyGenericView(parent) { doConnections(); }
Q_SIGNAL void mySignal();
#ifdef Q_MOC_RUN
Q_SLOT void mySlot1();
Q_SLOT void mySlot2();
Q_SLOT void mySlot3(); // for MOC only since we don't override it
#endif
};
Finally, this little test case shows that it indeed works as desired.
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyTreeWidget tree;
MyTableWidget table;
Q_ASSERT(!tree.slot1Invoked && !tree.slot2Invoked && !tree.slot3Invoked);
emit tree.mySignal();
Q_ASSERT(tree.slot1Invoked && tree.slot2Invoked && tree.slot3Invoked);
Q_ASSERT(!table.slot1Invoked && !table.slot2Invoked && !table.baseSlot3Invoked);
emit table.mySignal();
Q_ASSERT(table.slot1Invoked && table.slot2Invoked && table.baseSlot3Invoked);
return 0;
}
#include "main.moc"
This approach gives you the following:
The common code class derives from the base class, and can thus easily invoke or override the behavior of the base class. In this particular example, you can reimplement the QAbstractItemView methods etc.
There is full support for signals and slots. Even though the signals and slots are declared as such in the metadata of the derived class, you can still use them in the generic class.
In this situation you may make use of composition rather than multiple inheritance. Something like this:
class MySignaler : public QObject
{
Q_OBJECT
public:
MySignaler : QObject(NULL) {}
signals:
void MySignal();
}
MySignaler signaler;
class MyBaseWidgetContainer: public QWidget
{
Q_OBJECT
public:
MyBaseWidgetContainer() : QObject(NULL), widget(NULL)
{
connect(&signaler, SIGNAL(MySignal()), this, SLOT(MySlot()));
}
public slots:
virtual void MySlot()
{
// Default behavior here
}
private:
QWidget *widget;
}
class MyTabWidgetContainer : public MyBaseWidgetContainer
{
Q_OBJECT
public:
MyTabWidgetContainer() {
widget = new QTabWidget(this);
QLayout *layout = new QBoxLayout(this);
layout->addWidget(widget);
}
public slots:
void MySlot()
{
// Decide to handle the signal for custom behavior
}
}

How would I connect this signal to the slot

I would like to create a signal in my main class foo so that a static method in a different class could emit it.I just started of with QT so I am a bit confused. I currently have the following code
class Foo : public QMainWindow
{
Q_OBJECT
public:
Foo(QWidget *parent = 0, Qt::WFlags flags = 0);
~Foo();
signals:
void UpdateSignal(int val);
private slots:
void MySlot(int val);
};
Foo::Foo(QWidget *parent, Qt::WFlags flags): QMainWindow(parent, flags)
{
//How do I connect Bfoo::somemethod() here. I know its suppose to be like
connect(xx,SIGNAL(UpdateSignal(int)),this, SLOT(MySlot(int)));
ui.setupUi(this);
}
void Foo::MySlot(int val)
{
//Do something..
}
Now I have this class
Class Bfoo
{
static void somemethod()
{
emit UpdateSignal(12);
}
}
Any suggestions on how the static somemethod() could emit the UpdateSignal
When you emit signal it is necessary to know which object is emitting it. This is because signals are not implemented to be messages between different classes but messages between instances of (possibly different) classes.
Secondly, signals are protected methods. They are not accessible for external users. What you can do is define public method in Foo which will do the emission:
void Foo:EmitUpdateSignal(int x) {
emit UpdateSignal(x);
}
And then in your Bfoo::somemethod() you need to pass object which will emit signal:
void BFoo::somemethod(Foo &f) {
f.EmitUpdateSignal(12);
}
However, notice what you are doing. You emit signal which is connected to the slot in the same instance. This suggests design flaw but I cannot give any hints without more details about what are you going to achieve.