Qt5: New signal and slot syntax

I thought, that I should write about this topic, because it’s time to start my self-education project again and see how I can take new features of Qt in use. I’m not sure how useful this blog post is because there already is a nice wiki page available about the same topic on qt-project.org. But for those, who haven’t read the wiki page, this might be a bit shock – Yes, in Qt5 there is a new syntax for connecting signals and slots!

Don’t worry, your old code (Qt 4.x) doesn’t break and Trolls will continue the support of the old, string-based connection. So what’s new in the new signal-slot syntax then? Basically you can connect signals and slots using the following style shown in by the example below. Note that you still have to have Q_OBJECT macro defined in a class, which introduces signals or slots.

connect(sender, &Sender::valueChanged, receiver, &Receiver::updateValue );

Instead of using SIGNAL() and SLOT() macros, you can now also use C++ function pointers to connect signals and slots. In Qt5, you can connect signals to any member function of a class  i.e. they don’t need to be slots. Note that in the end, Qt slots are only class’ member functions. The “slots” keyword is only an empty define and used only by MOC (Meta Object Compiler) when parsing headers.

Let’s have a few examples how new syntax looks like. You can have a class like below:

class MyClass : public QObject
{
    Q_OBJECT

public:
    explicit MyClass(QWidget *parent = 0);
    void myMethod(QVariant x);

signals:
    void mySignal1(int x);
    void mySignal2(QString x);

public slots:
    void buttonClicked();
    void mySlot(int x);
};

// Standard, non-member-function
static void myFunction()
{
    qDebug() << "My Function called";
}

Now if you want to connect signals to slots or class member functions you can do it  like shown below:

// this pointer is an instance of MyClass
connect(this, &MyClass::mySignal1, this, &MyClass::mySlot1);

// Connect to class member function with implicit type conversion from QString to QVariant
connect(this, &MyClass::mySignal2, this, &MyClass::myMethod);

// Connect mySignal() signal to non-slot function myFunction()
connect(this, &MyClass:mySignal, &myFunction);

Personally, I think the new syntax makes signal-slot connection more flexible. In addition to this it’s even possible to use new C++11 standard features (tr1::bind and lambda) and connect signals e.g. to lambda functions. Unfortunately my experiment of using lambda functions failed because clang 3.1 on OSX crashed when having a lambda function in my code. I should try it on Linux with GCC later.

Strongly Typed Enumerations

C++11 introduces “Strongly typed enumerations”. Unlike C++03 enumerations, strongly typed enumerations are type-safe. In C++03 you can define an enumeration and compare it with an integer or with another enumeration “type” and it just works. Strongly typed enumerations remove this problem, because they are not implicitly converted to integers.  In C++11, you can use the following syntax to define a strongly typed enumeration:

enum class MyEnumeration{
    Value1,
    Value2,
    Value3
};

Using strongly typed enumerations, code is safer and it’s especially useful if using those as signal and slot arguments. That combined to the new signal and slot syntax may help you to write better code too. I just wanted to mention about strongly typed enumerations here even though they have nothing to do with Qt.

Pros and cons of new syntax

There is a good list of pros and cons in the original article so you can read it through to get the whole list of what’s good,  bad and ugly. I thought to show here only a few of the advantages and disadvantages of using the new syntax.

The old string-based syntax works pretty well and is one of the key features of Qt, but it’s not perfect. I believe everyone, who has worked with Qt has sometimes failed to make a signal-slot connection, but you can’t catch that in compile time. If the connection fails, you’ll get only a warning when running your application.  Using the new signal-slot connection syntax, you can catch connection errors at the compile time.

According the original article’s pros and cons list, they claim that more complicated syntax is one of the cons. Personally I disagree this when dealing with a standard case (no overloading). With the new syntax, it’s easier to avoid errors. For example now you don’t need to provide a list of signal or slot argument types, only function pointers. I think, this is definitely a pro as shown below.

    connect(this, &MyClass::mySignal, this, &MyClass::mySlot);
vs.
    connect(this, SIGNAL(mySignal(int)), this, SLOT(mySlot(int)));

Even though I have a long history with Qt, I prefer to the new way of making signal-slot connection. But it’s true, when there’s overloading in use, you might end up of doing nasty looking static_cast calls, which don’t improve the readability of a code.

Disconnecting signals in Qt 5 is a bit more complicated. Check the original article to see the example, but basically you need to maintain a list of connections (QObject::Connection) and call QObject::disconnect( ..) to each of the connection you want to disconnect. Naturally if using the old way, you can also disconnect using the old way.

One of the biggest advantage of the new syntax is ability to connect signals directly to class’s member functions or other non-member-functions which aren’t explicitly defined to be slots.

Conclusion

I was a bit surprised when I ran into this new signal slot syntax first time, but it’s very motivating to see that even these kind of corner stones of Qt can be develop further and be improved. It’s hard to say at this point, is the new way really better and do I gain much benefit comparing it to the string-based syntax.

As stated in a pros and cons chapter, there are clear cases where the new approach might save some time, but on the other hand, cases like overloading may not improve the readability of the code. Also disconnecting signals, requires more with the new syntax. One clear benefit of the new syntax is, possibility to connect lambda or other functions to signals. When a “slot” should do a simple, one-liner task, you don’t  need to modify you header just because there’s a need for a new private slot.

So no right or wrong here, but I think this is progress, which is alway good.

Thanks for reading my blog!

 

 

 

 

Tags: , , ,

2 Responses to “Qt5: New signal and slot syntax”

  1. e8johan says:

    From a pure hacking-up-a-quick-example perspective, i personally like the ability to connect to non-class member functions. It is often I find myself creating a complete class just to be able to add a slot doing a basic task. The rest of the example is usually common components. Now, I can just add my function to the main cpp file and connect directly to it.

Leave a Reply

You must be logged in to post a comment.