Trusted Software Excellence across Desktop and Embedded
Take a glance at the areas of expertise where KDAB excels ranging from swift troubleshooting, ongoing consulting and training to multi-year, large-scale software development projects.
Find out why customers from innovative industries rely on our extensive expertise, including Medical, Biotech, Science, Renewable Energy, Transportation, Mobility, Aviation, Automation, Electronics, Agriculture and Defense.
High-quality Embedded Engineering across the Stack
To successfully develop an embedded device that meets your expectations regarding quality, budget and time to market, all parts of the project need to fit perfectly together.
Learn more about KDAB's expertise in embedded software development.
Where the capabilities of modern mobile devices or web browsers fall short, KDAB engineers help you expertly architect and build high-functioning desktop and workstation applications.
Extensible, Safety-compliant Software for the Medical Sector
Create intelligent, patient-focused medical software and devices and stay ahead with technology that adapts to your needs.
KDAB offers you expertise in developing a broad spectrum of clinical and home-healthcare devices, including but not limited to, internal imaging systems, robotic surgery devices, ventilators and non-invasive monitoring systems.
Building digital dashboards and cockpits with fluid animations and gesture-controlled touchscreens is a big challenge.
In over two decades of developing intricate UI solutions for cars, trucks, tractors, scooters, ships, airplanes and more, the KDAB team has gained market leading expertise in this realm.
Build on Advanced Expertise when creating Modern UIs
KDAB assists you in the creation of user-friendly interfaces designed specifically for industrial process control, manufacturing, and fabrication.
Our specialties encompass the custom design and development of HMIs, enabling product accessibility from embedded systems, remote desktops, and mobile devices on the move.
Legacy software is a growing but often ignored problem across all industries. KDAB helps you elevate your aging code base to meet the dynamic needs of the future.
Whether you want to migrate from an old to a modern GUI toolkit, update to a more recent version, or modernize your code base, you can rely on over 25 years of modernization experience.
KDAB offers a wide range of services to address your software needs including consulting, development, workshops and training tailored to your requirements.
Our expertise spans cross-platform desktop, embedded and 3D application development, using the proven technologies for the job.
When working with KDAB, the first-ever Qt consultancy, you benefit from a deep understanding of Qt internals, that allows us to provide effective solutions, irrespective of the depth or scale of your Qt project.
Qt Services include developing applications, building runtimes, mixing native and web technologies, solving performance issues, and porting problems.
KDAB helps create commercial, scientific or industrial desktop applications from scratch, or update its code or framework to benefit from modern features.
Discover clean, efficient solutions that precisely meet your requirements.
Boost your team's programming skills with in-depth, constantly updated, hands-on training courses delivered by active software engineers who love to teach and share their knowledge.
Our courses cover Modern C++, Qt/QML, Rust, 3D programming, Debugging, Profiling and more.
The collective expertise of KDAB's engineering team is at your disposal to help you choose the software stack for your project or master domain-specific challenges.
Our particular focus is on software technologies you use for cross-platform applications or for embedded devices.
Since 1999, KDAB has been the largest independent Qt consultancy worldwide and today is a Qt Platinum partner. Our experts can help you with any aspect of software development with Qt and QML.
KDAB specializes in Modern C++ development, with a focus on desktop applications, GUI, embedded software, and operating systems.
Our experts are industry-recognized contributors and trainers, leveraging C++'s power and relevance across these domains to deliver high-quality software solutions.
KDAB can guide you incorporating Rust into your project, from as overlapping element to your existing C++ codebase to a complete replacement of your legacy code.
Unique Expertise for Desktop and Embedded Platforms
Whether you are using Linux, Windows, MacOS, Android, iOS or real-time OS, KDAB helps you create performance optimized applications on your preferred platform.
If you are planning to create projects with Slint, a lightweight alternative to standard GUI frameworks especially on low-end hardware, you can rely on the expertise of KDAB being one of the earliest adopters and official service partner of Slint.
KDAB has deep expertise in embedded systems, which coupled with Flutter proficiency, allows us to provide comprehensive support throughout the software development lifecycle.
Our engineers are constantly contributing to the Flutter ecosystem, for example by developing flutter-pi, one of the most used embedders.
KDAB invests significant time in exploring new software technologies to maintain its position as software authority. Benefit from this research and incorporate it eventually into your own project.
Start here to browse infos on the KDAB website(s) and take advantage of useful developer resources like blogs, publications and videos about Qt, C++, Rust, 3D technologies like OpenGL and Vulkan, the KDAB developer tools and more.
The KDAB Youtube channel has become a go-to source for developers looking for high-quality tutorial and information material around software development with Qt/QML, C++, Rust and other technologies.
Click to navigate the all KDAB videos directly on this website.
In over 25 years KDAB has served hundreds of customers from various industries, many of them having become long-term customers who value our unique expertise and dedication.
Learn more about KDAB as a company, understand why we are considered a trusted partner by many and explore project examples in which we have proven to be the right supplier.
The KDAB Group is a globally recognized provider for software consulting, development and training, specializing in embedded devices and complex cross-platform desktop applications.
Read more about the history, the values, the team and the founder of the company.
When working with KDAB you can expect quality software and the desired business outcomes thanks to decades of experience gathered in hundreds of projects of different sizes in various industries.
Have a look at selected examples where KDAB has helped customers to succeed with their projects.
KDAB is committed to developing high-quality and high-performance software, and helping other developers deliver to the same high standards.
We create software with pride to improve your engineering and your business, making your products more resilient and maintainable with better performance.
KDAB has been the first certified Qt consulting and software development company in the world, and continues to deliver quality processes that meet or exceed the highest expectations.
In KDAB we value practical software development experience and skills higher than academic degrees. We strive to ensure equal treatment of all our employees regardless of age, ethnicity, gender, sexual orientation, nationality.
Interested? Read more about working at KDAB and how to apply for a job in software engineering or business administration.
All Qt developers have asked themselves at least once in their careers: "why isn't my slot invoked?" (I've asked myself that question many, many times).
There are a number of reasons why a connection may fail to be properly set up, and ultimately cause our slot not to be invoked. This blog post is a practical series of checks to help you debug these sorts of issues.
0. Was the slot really not invoked?
First and foremost, are we really sure that the slot was not invoked? A simple way to rule this out is by adding a debug print in the slot, or running the application in a debugger and setting a breakpoint.
Keeping a debug print in place is also useful to know when we have finally fixed the problem, and the slot is getting invoked as expected.
1. Was the connection established in the first place?
A QObject::connect() statement may fail to connect a signal to a slot for various reasons. Here's a non-comprehensive list:
The sender is nullptr
The receiver is nullptr
The signal does not exist for the given sender (*)
The slot does not exist for the given receiver (*)
The signal/slot argument lists is not compatible (*)
The elements marked with a (*) do not fully apply to the new connection syntax, which performs checks at compile-time.
When QObject::connect() fails it returns false and it emits a warning which gets typically printed on the console, if you have one, or in Creator's output pane.
In practice this means we have a couple of options to test if this is happening:
we can test the return value (for instance, by adding an assertion), or
we can make all warnings fatal by exporting the QT_FATAL_WARNINGS environment variable and setting it to a non-zero value. (Of course, this is only doable if our application is warning free...)
For instance, we can do this:
// connect() actually returns a QMetaObject::Connection object,// which implicitly converts to bool.constbool connected =connect(sender,&Sender::aSignal, receiver,&Receiver::aSlot);qDebug()<<"Connection established?"<< connected;
Whatever you do, do not wrap your connect() statement in an assert!
This is wrong:
// do not do this!Q_ASSERT(connect(sender,&Sender::aSignal, receiver,&Receiver::aSlot));
2. Are the sender and the receiver objects still alive?
Qt automatically breaks a signal/slot connection if either the sender or the receiver are destroyed (or if context object is destroyed, when using the new connection syntax and connecting to free functions). This is a major feature of the signals and slots mechanism. However, in complicated software architectures, and when dealing with long-lived objects, we might end up in a situation where indeed a connection was broken because one side of it had been destroyed.
Again, there are a couple of ways to be sure that we didn't accidentally delete the sender and/or the receiver. One is by adding a breakpoint in their destructors. Bonus points if we make it conditional on the specific objects, for instance like this:
(gdb) b 'QObject::~QObject()' if (this == 0x12345678)
However, this strategy is a bit cumbersome in practice: we may need a debug build of Qt and of our application; we need to figure out the address of the object in question (say, by having another breakpoint on the connect statement and inspecting the locals), and these addresses change at every run; and so on.
An easier approach is to connect to the QObject::destroyed() signal, and output a debug message:
connect(sender,&Sender::aSignal, receiver,&Receiver::aSlot);// be sure that sender and receiver didn't get destroyed:connect(sender,&QObject::destroyed,[]{qDebug()<<"Sender got deleted!";});connect(receiver,&QObject::destroyed,[]{qDebug()<<"Receiver got deleted!";});
3. Was the signal emitted at all?
It's a fair question to ask, especially when the signal is coming from Qt itself or from a third-party library we have no control over. If the signal is not getting emitted, obviously the slot will never be called.
Once more, a breakpoint on the signal itself (remember that signals are ordinary member functions) or a lambda connected to it, can immediately show whether the signal is being emitted or not.
4. Is the connection queued?
Queued connections deserve some special care: for a queued connection to work, there are extra requirements compared to a direct connection. The requirements are:
that an event loop is running in the thread the receiver has affinity with;
that all the arguments carried by the signal are registered in the meta-type system.
Running an event loop
The first requirement comes from the fact that a queued connection under the hood is implemented by posting an event to the receiver. The handling of this event will invoke the slot. However, for that event to be dispatched, we need a running event loop.
Running an event loop can be achieved in a number of ways: calling QCoreApplication::exec() in the main thread, or QThread::exec() in another thread, or using QEventLoop, and so on.
Registering the signal's arguments in the meta-type system
The second requirement is a consequence of the first: when a queued connection is activated, Qt needs to copy the arguments of the signal into the event sent to the receiver. In order to do so, it needs a bit of help from the user: all the types of the arguments must be registered in Qt's meta-type system.
The good news is that all the C++ fundamental types and many Qt datatypes are already registered and will just work. The bad news is that any other datatype is not registered, in which case the connection will not work and we will get a warning on the console.
The solution is simple: use the Q_DECLARE_METATYPE macro and the qRegisterMetaType() template function -- which by the way is exactly what the warning suggests you to do anyhow. See, it's a good thing to look for warnings on the console!
For instance, if we need to establish a queued connection for a signal carrying a MyClass argument, we'll need to modify the class' definition:
// objects of this type are passed as arguments to some signal// in a queued invocationclassMyClass{/* ... */};// add this:Q_DECLARE_METATYPE(MyClass);
and add the following statement somewhere, making sure that it runs before the signal is emitted for the first time (or before the connection is established, if we're forcing the connection type to queued):
qRegisterMetaType<MyClass>();// do not pass any argument
We may add this call to MyClass' constructor, or in main, or in some other initialization code. It is safe to call qRegisterMetaType() more than once.
Note that, as far as the meta-type system is concerned, MyClass, MyClass *, QVector<MyClass>, shared_ptr<MyClass> and so on are all different types, and as such, each one may need its own registration.
Debugging signals and slots connections
In the final part of this blog post, I'd like to offer a couple of broader suggestions to inspect and debug signals and slots issues.
How do I check if a connection is queued?
If we do not explicitly choose a connection type, then QObject::connect() defaults to Qt::AutoConnection. This connection type means:
if the thread that invokes the signal is the same thread the receiver has affinity with, use a direct connection;
(otherwise) if the thread that invokes the signal is not the same thread the receiver has affinity with, use a queued connection.
You can see this decision in action here on line 3686.
Note how:
the thread affinity of the sender object does not matter at all;
the decision is taken at signal emission time (and therefore its outcome may change, for instance if the receiver object changes thread affinity).
Apart from adding a breakpoint in Qt's internals, an easy way to debug whether a signal activation is direct or queued is doing the same test and showing the outcome:
// the connect to debugconnect(sender,&Sender::aSignal, receiver,&Receiver::aSlot);// add:connect(sender,&Sender::aSignal,// same sender and signal receiver,// context object to break this connection[receiver](){// debug outputqDebug()<<"Direct?"<<QThread::currentThread()== receiver->thread();}, Qt::DirectConnection);// see below
In the second connect(), we make use of the context object to automatically break the connection in case receiver gets destroyed; otherwise, we would risk running the lambda on a dangling pointer.
On the other hand, specifying the context object makes the lambda run in receiver's thread by default, making our debug output useless. For this reason, the connection type gets forced to Qt::DirectConnection, so that the lambda is invoked by the same thread that emits the signal.
Checking all the signals and slots connected to an object
It is possible to display all the connections established from and towards a given QObject (that is, that have that object as a sender or as a receiver). There are (at least) two ways for doing this.
QObject::dumpObjectInfo()
A straightforward way to see all the inbound and outbound signals is to add a call to QObject::dumpObjectInfo() on a given QObject. Since Qt 5.8 this function is unconditionally available for Qt users (cf. the small patch I made); before, using this function required a debug build of Qt (otherwise, it was a no-op).
This is an example of QObject::dumpObjectInfo()'s output:
OBJECT TextEdit::unnamed
SIGNALS OUT
signal: destroyed(QObject*)
signal: destroyed()
signal: objectNameChanged(QString)
<functor or function pointer>
signal: iconSizeChanged(QSize)
--> QToolBar::unnamed _q_updateIconSize(QSize)
SIGNALS IN
<-- QClipboard::unnamed <unknown>
<-- QTextDocument::unnamed <unknown>
<-- QAction::unnamed <unknown>
<-- QComboBox::comboSize <unknown>
(I've removed some lines from the output to keep it compact).
Basically, for each signal declared in the object, we get a list of what is currently connected to it. Similarly, we get a list of all the connections using the object as the receiver. For each object we also get its type and its object name (in the sense of QObject::objectName; unnamed means that the name is empty).
As you can notice the big problem we have here is that the new style connection syntax does not allow to display the function's name in a pretty way, and all we get is a placeholder. On the other hand, the old-style connections get the full signature printed. Remapping a function pointer to its symbol name is quite complex, and no-one wants to add that machinery to Qt itself (after all, if you need it, you can always start a debugger).
GammaRay
GammaRay, the Qt Swiss-army knife, is also able to visualize all the connections for a given QObject. Once you have started it, go in the Objects pane, select the object you want to inspect and check its connections in the Connections tab:
GammaRay showing all the connections for a QObject
By the way, GammaRay will also tell you if you have signals carrying arguments which are not registered in the metatype system. For this, switch to the Methods tab, which lists all the meta-methods (signals, slots, invokables):
GammaRay showing signals which carry arguments which are unregistered metatypes
Conclusion
With this blog post, I have provided Qt users with a short, handy guide to know better their signals and slots connections and what to do in case they experience trouble.
About KDAB
Trusted software excellence across embedded and desktop platforms
The KDAB Group is a globally recognized provider for software consulting, development and training, specializing in embedded devices and complex cross-platform desktop applications. In addition to being leading experts in Qt, C++ and 3D technologies for over two decades, KDAB provides deep expertise across the stack, including Linux, Rust and modern UI frameworks. With 100+ employees from 20 countries and offices in Sweden, Germany, USA, France and UK, we serve clients around the world.
Off topic: What is the reason that KDAB does not provide the whole content of its articles in the RSS feed any longer? It makes reading the interesting KDAB articles from within my RSS reader quite complicated. Could this be fixed? Thanks and keep up the great blog posts!
11 - Mar - 2017
Giuseppe D'Angelo
Hi,
I believe I replied already in the other blogpost.
10 - Mar - 2017
Federico
I'd add a case 1.5: has the signal already been connected to the slot?
The simple case is a constructor that emits a signal: no connection can be already in place, so the signal is just a nop. A more difficult case may be some initialization done in the constructor, and this initialization may cause an immediate emission of a signal, depending on some other conditions.
11 - Mar - 2017
Giuseppe D'Angelo
Good tip!
14 - Mar - 2017
Christian
Hi,
could you explain why having Q_ASSERT around connect statements is such a bad idea? Is it the implicit conversion from QMetaObject::Connection to bool?
17 - Mar - 2017
Giuseppe D'Angelo
Hi Christian,
The problem comes from the fact that a Q_ASSERT gets completely removed in release mode by default. Having any code with side effects (such as a connect statement) in a Q_ASSERT is therefore dangerous -- it will get removed in a release build.
3 - Jan - 2021
Doug Rogers
I would add that signal/slots can fail across threads in the connection type is not correct.
Signals will also fail if the argument is not registered.
That's correct. Actually, even in Qt 5 connect returns a connection object -- which implictly converts to bool anyhow, so you can test it directly (if you don't care about disconnecting using that connection object).
3 - Jan - 2021
Doug Rogers
Signals will also not be sent if blockSignals(true) has been called.
4 - Jan - 2021
Giuseppe D'Angelo
Very good point -- thanks!
7 - Oct - 2021
George
Slot will also not be invoked if the signal is explicitly disconnected from a parcticular slot (or all the slots). It may be obvious, but it doesn't hurt to check whether you have a line of code such as disconnect(sender, &Sender::signal, nullptr, nullptr); in your application.
8 - Oct - 2021
Giuseppe D'Angelo
Hi,
Sure, it makes total sense to check for that. The techniques discussed at the end of the post should allow you to spot that the signal is not connected (any more), hence one should investigate why, and clearly a disconnection can be the reason. Thanks!
Giuseppe D’Angelo
Senior Software Engineer
Senior Software Engineer at KDAB. Giuseppe is a long-time contributor to Qt, having used Qt and C++ since 2000, and is an Approver in the Qt Project. His contributions in Qt range from containers and regular expressions to GUI, Widgets, and OpenGL. A free software passionate and UNIX specialist, before joining KDAB, he organized conferences on opensource around Italy. He holds a BSc in Computer Science.
Our hands-on Modern C++ training courses are designed to quickly familiarize newcomers with the language. They also update professional C++ developers on the latest changes in the language and standard library introduced in recent C++ editions.
12 Comments
10 - Mar - 2017
Tim
Off topic: What is the reason that KDAB does not provide the whole content of its articles in the RSS feed any longer? It makes reading the interesting KDAB articles from within my RSS reader quite complicated. Could this be fixed? Thanks and keep up the great blog posts!
11 - Mar - 2017
Giuseppe D'Angelo
Hi, I believe I replied already in the other blogpost.
10 - Mar - 2017
Federico
I'd add a case 1.5: has the signal already been connected to the slot?
The simple case is a constructor that emits a signal: no connection can be already in place, so the signal is just a nop. A more difficult case may be some initialization done in the constructor, and this initialization may cause an immediate emission of a signal, depending on some other conditions.
11 - Mar - 2017
Giuseppe D'Angelo
Good tip!
14 - Mar - 2017
Christian
Hi, could you explain why having Q_ASSERT around connect statements is such a bad idea? Is it the implicit conversion from QMetaObject::Connection to bool?
17 - Mar - 2017
Giuseppe D'Angelo
Hi Christian, The problem comes from the fact that a Q_ASSERT gets completely removed in release mode by default. Having any code with side effects (such as a connect statement) in a Q_ASSERT is therefore dangerous -- it will get removed in a release build.
3 - Jan - 2021
Doug Rogers
I would add that signal/slots can fail across threads in the connection type is not correct. Signals will also fail if the argument is not registered.
Also, in Qt6, connect does not return a bool.
https://doc-snapshots.qt.io/qt6-dev/qobject.html#connect-1
4 - Jan - 2021
Giuseppe D'Angelo
Hi,
That's correct. Actually, even in Qt 5 connect returns a connection object -- which implictly converts to bool anyhow, so you can test it directly (if you don't care about disconnecting using that connection object).
3 - Jan - 2021
Doug Rogers
Signals will also not be sent if blockSignals(true) has been called.
4 - Jan - 2021
Giuseppe D'Angelo
Very good point -- thanks!
7 - Oct - 2021
George
Slot will also not be invoked if the signal is explicitly disconnected from a parcticular slot (or all the slots). It may be obvious, but it doesn't hurt to check whether you have a line of code such as disconnect(sender, &Sender::signal, nullptr, nullptr); in your application.
8 - Oct - 2021
Giuseppe D'Angelo
Hi, Sure, it makes total sense to check for that. The techniques discussed at the end of the post should allow you to spot that the signal is not connected (any more), hence one should investigate why, and clearly a disconnection can be the reason. Thanks!