C++ Programming

Qt Signals and Slots explained with Example Codes

Qt Signals and slots:

Qt Signals and Slots-GUI programming always follows the same principle: If, for example, a widget has changed (e.g. when clicking a button), if you want to inform another widget about it. So widgets are in the program linked to a function that is executed as soon as the user activated this with a click of the mouse. If the user presses e.g. an “Open” button, a corresponding function is called, which may be used. Presented a new dialog for opening a file.

Many graphical toolkits use them for communication between the widgets, often a callback function. Such a callback is nothing but a simple pointer on a function. However, such callbacks have two minor flaws. To the one they are not type-safe (one is never sure that the currently executing Function calls the callback with the correct arguments). Second is, the Callback is permanently linked to the function to be executed because the Function needs to know which callback is to be called.

With the Qt signal and Qt slot concept, Qt takes a slightly different approach. This Concept has the advantage that Qt automatically disconnects if one of the communicating objects is destroyed. This avoids many Crashes because attempts to access a nonexistent object do not more are possible.

The easiest way to see the Qt signal and Qt slot concept, just to copy and paste the below code in Qt creator. This example illustrates how a button performs the quit action on the application.

#include <QApplication>
#include <QPushButton>

int main(int argc, char *argv[])
{
   QApplication a(argc, argv);
   QPushButton btn_close("Close");
   btn_close.resize(600, 200);
   btn_close.show();
   QObject::connect( &btn_close, SIGNAL( clicked() ),
   &a, SLOT( quit() ) );
    return a.exec();
}

output:

Qt Signals and Slots


Amazon Purchase Links:

Top Gaming Computers

Best Laptops

Best Graphic Cards

Portable Hard Drives

Best Keyboards

Best High Quality PC Mic

Computer Accessories

*Please Note: These are affiliate links. I may make a commission if you buy the components through these links. I would appreciate your support in this way!

Compared to the first helloworld example here, apart from one other Name of the button, with line 10 a new static method is called. Connect () from the QObject class.

connect () is a static method that establishes a connection between one signal and one slot. The exact syntax for this:

bool QObject::connect (

const QObject * sender, const char * signal,

const QObject * receiver, const char * method,

Qt::ConnectionType type = Qt::AutoCompatConnection )

[static]

The first two arguments (sender, signal) denote the object that picks up a signal and sends it to the receiver – the sender object. The other two arguments (receiver, method) set the object of the receiver of the slot to be accepted. More precisely: receive that if the object sends the signal, it is bound to the slot. This takes that Object receiver from the slot and executes the method. On the following line related, that means:

QObject::connect( &btn_close, SIGNAL( clicked() ),

   &a, SLOT( quit() ) );

With this you connect the object btn_close from the class QPushButton with the Object app from class QApplication. Should the signal be at the button clicked(), specify the action that the QApplication the quit () method is executed, which in this case is the end of the program would mean (see Figure1).

Qt Signals and Slots
Figure 1: Connect two objects

The function QObject :: connect () returns true if the connection is successful, otherwise returns false. You must also use the SIGNAL() and SLOT() macros use when you want to set the signal and method because for that a character string is provided for both arguments and these two macros for it ensure that a correct character string is used.

Thus, the slots are completely normal methods of a class that react to signals of another class, which signals are basically in turn are just simple methods of a class. Of course it is also possible to link a transmitter with several receivers and vice versa. Is For example, if a signal is connected to two or more slots, the slots are the Executed in sequence as written in code. Any subclass from QObject can thus define such signals and slots.




Another example is to be created for this, the following signal-slot concept used (see Figure 2).

Qt Signals and Slots
Figure 2: Connect signals and slots

The drawing is easy to read. On the left side all objects are given, which receive a signal and send it to the objects on the right. So on the left side there are the signals (with their classes) and on the right side the slots (with their classes).

The example uses four buttons of the QPushButton class, a widget called QWidget, which represents the framework, and of course the QApplication class, without which no GUI application can do.

The button but1 was connected to two slots here. Does this button get that Signal clicked (), the slot aboutQt () of the class QApplication and then the slot showNormal() from the class QWidget. aboutQt() is a simple message box about Qt and showNormal() is equivalent the system menu entry Restore the window. Was e.g. The size of the window changes, this slot ensures that the window is restored is returned to its original size.

Two more buttons were also connected to slots of the QWidget class. If the button but2 receives the signal clicked (), the slot becomes with QWidget showMaximized() executed. The window is the same size as the desktop maximized. The same applies to button but3, only that the window is minimized becomes. The last button (but4) was again with QApplication and its Slot quit() connected. So if but4 receives the clicked() signal, the Application terminated.

#include <QApplication>
#include <QPushButton>
#include <QVBoxLayout>
#include <QLabel>

int main(int argc, char *argv[])
{
   QApplication app(argc, argv);
   QWidget* win = new QWidget;
   QVBoxLayout* layout = new QVBoxLayout(win);
   QPushButton* but1 = new
   QPushButton("About Qt");
   QPushButton* but2 = new QPushButton("Maximize");
   QPushButton* but3 = new QPushButton("Minimize");
    QPushButton* but4 = new QPushButton("Close");
// size of the buttons
    but1->resize(100, 30);
    but2->resize(100, 30);
    but3->resize(100, 30);
   but4->resize(100, 30);
    // add widgets to the vertical box
    layout->addWidget(but1);
    layout->addWidget(but2);
    layout->addWidget(but3);
   layout->addWidget(but4);
   // make signal-and-slot connections
    QObject::connect( but1, SIGNAL( clicked() ),
   &app, SLOT( aboutQt() ) );
    QObject::connect( but1, SIGNAL( clicked() ),
   win, SLOT( showNormal() ) );
   QObject::connect( but2, SIGNAL( clicked() ),
   win, SLOT( showMaximized() ) );
    QObject::connect( but3, SIGNAL( clicked() ),
   win, SLOT( showMinimized() ) );
    QObject::connect( but4, SIGNAL( clicked() ),
   &app, SLOT( quit() ) );
    // show window
    win->show();
    return app.exec();
}

Output:


Mutual signal and slot concept:

In addition, it often happens that two widgets are dependent on each other. If, for example, one widget is changed, the other one must also adapt to this change can be adjusted – and vice versa as well. It’s best to see yourself the following figure (3).

Qt Signals and Slots
Figure 3:Adjustment of two widgets in case of changes

In this example, you have a QSpinBox class and a QSlider class that both adjust the value of the other widget in the event of a change. If, for example, the value was changed in the spin box, the signal becomes valueChanged() triggered. If this is the case, the slider (QSlider) will move accordingly adapted to the spinbox with the slot setValue(). Viewed differently, have the same case. valueChanged() is the signal and setValue() the slot of the two widgets.

To connect the two widgets together, there are basically only two connections with connect () necessary. Here is the corresponding program example:

#include <QApplication>
#include <QVBoxLayout>
#include <QSpinBox>
#include <QSlider>

int main(int argc, char *argv[])
{
   QApplication app(argc, argv);
   QWidget* win = new QWidget;
   QVBoxLayout* layout = new QVBoxLayout(win);
   QSpinBox* spin = new QSpinBox;
   QSlider* slider = new QSlider(Qt::Horizontal);
   // Minimum-maximum value for spinbox
    spin->setMinimum(0);
    spin->setMaximum(100);
   // Minimum-maximum value for slider
   slider->setMinimum(0);
   slider->setMaximum(100);
   // add widgets
   layout->addWidget(spin);
   layout->addWidget(slider);
    // signal-and-slot connection
    QObject::connect( spin, SIGNAL( valueChanged(int) ),
   slider, SLOT( setValue(int) ) );
   QObject::connect( slider, SIGNAL( valueChanged(int) ),
   spin, SLOT( setValue(int) ) );
    win->show();
    return app.exec();
}

Output:

Qt Signals and Slots

If you change the slider here, the spin box will also automatically provided / changed the corresponding value. Change the spin box with the arrows or as a valid value through the keyboard input, the Slider adjusted accordingly to the position.


Define your own class with Qt signals and slots:

To provide a class with its own signals and slots, the following applies Rules to be followed:

  • You cannot define your own event class that only consists of signals and slots. The signals and slots must always be part of the class represent.
  • Own signals and slots can only be defined in classes that are supported by the Class QObject are derived.
  • The macro Q_OBJECT must be set in the newly defined class.
  • There are no standard parameters for signals and slots for separate classes allowed.

To describe how you can create your own signals and slots in a derived class define, the following normal C ++ class should first be used as a comparison:

// typical form of a simple C ++ class

class MyClass {

public:

// constructor

MyClass ();

// access methods

int value () const {return val; }

void setValue (int);

private:

int val;

};

In order to create a real Qt class, the following (highlighted in bold) Changes needed:

// a real Qt class

class MyClass: public QObject {

Q_OBJECT

 public:

 // constructor

 MyClass ();

// access methods

int value () const {return val; }

 public slots:

void setValue (int);

signals:

void valueChanged (int);

private:

int val;

};

Now that you’ve derived your class from QObject on line 1, you can use Signals and declare slots basically like normal methods. However, may the declared signal and slot member functions do not have a return type and must therefore be void. However, you can use any Use number and any type.

The Q_OBJECT macro from line 2 is also important (attention, without semicolon!). In the declaration of the signal and slot member functions are also the new Specifier signals (line 10) and slots (line 8) used. Depending on the desired visibility to the outside world or the ability to be inherited the specifiers private, public and protected are set in front of signals and slots.



In your capacity as a programmer, you only define the slots as ordinary Member functions (methods). Qt beginners studying source code are often confused because they do not match the definition of the signal element function Find. The code for signal member functions is not, however, created by the programmer, but written by the Meta Object Compiler (MOC for short).

Here is an example that initially does not use any GUI elements. We’ll create a simple class with an integer property and implement the valueChanged (int) signal in this class, which is triggered

as soon as the integer value of the object is changed. Implement naturally we also set the corresponding slot setValue (int) to two To be able to link objects of the class with connect (). Here first the Declaration of the class MyClass.h:

#ifndef MYCLASS_H
#define MYCLASS_H
#include <QObject>

// A class that has signals and slots.
class MyClass: public QObject
{
    Q_OBJECT
public:
    MyClass();
    int value() const { return val;}
    public slots:
    // The value of "val" is changed.
    void setValue( int );
    signals:
    // The signal should be sent out,
     // when "val" is changed.
     void valueChanged (int);
private:
 int val;

};

#endif // MYCLASS_H

The definition of the class is just as simple. Because we don’t define the signal In this case, the constructor and the slot member function are sufficient setValue (int).

#include "myclass.h"

MyClass::MyClass()
{
    val = 0;

}
void MyClass::setValue( int v ) {
    // val is only set a new,
     // if a different value is actually passed.
 if ( v != val ) {
 val = v;
emit valueChanged(v);
 }
 }

Line 10 with the emit signal identifier is noticeable here. With the identifier emit you make it clear that the call is not a normal one Is a function call, but a signal call. However, achieve You emit the same without an identifier. The identifier is only intended to be able to recognize immediately whether it is a signal call. This is followed by the main function, apart from the message boxes (QMessageBox) also works without GUI elements and its own signal slot Concept demonstrated.




Main.cpp code:

#include "myclass.h"
#include <QApplication>
#include <QMessageBox>
#include <QString>
// simple message box
 void MyMessageBox(MyClass& a,MyClass& b,QString title) {
 QString Qstr, Qval;
 // Tinker the string together
 Qstr.append(title); Qstr.append("\na: ");
 Qval.setNum(a.value()); Qstr.append(Qval);
 Qstr.append("\nb: "); Qval.setNum(b.value());
 Qstr.append(Qval);
 QMessageBox::information(
NULL, "MyClass Information", Qstr, QMessageBox::Ok);
 }
 int main(int argc, char *argv[]) {
 QApplication app(argc, argv);
 // Two MyClass objects
 MyClass *a = new MyClass();
 MyClass *b = new MyClass();
 // The signal of the one is sent to the slot
  // connected to the other object.
 QObject::connect( a, SIGNAL( valueChanged(int) ),
b, SLOT( setValue(int) ) );
 // b.val gets the value 100
 b->setValue( 100 );
 MyMessageBox(*a, *b, "b->setValue(100)");
 // a.val gets the value 99. Through the signal slot
  // Link now also gets the value 99 for b.val
 a->setValue( 99 );
 // The proof
 MyMessageBox(*a, *b, "a->setValue(99)");
 return 0;
 }

You can ignore lines 5 to 13 here. This just becomes a message box displayed on the screen with the content of the integer values ​​of the two Objects that are newly created in lines 17 and 18. In line 21 we link these objects. If you change the value of object a, the valueChanged () signal is triggered and with object b and the slot setValue () connected. So as soon as you change the value of object a, will the value of object b is adjusted with our self-created slot setValue (). In this example, object b is given the same value as Object a. In line 23, object b is assigned a new value with 100. We have not established a signal-slot association, a and b have the following Values ​​(see Figure 4):

Qt Signals and Slots
Figure 4: After object b has received a value


In line 28 we then assign a new value to object a with 99. And our set up signal-slot connection is also activated immediately, see above that object b also receives the same value as object a. This results in the following values ​​(see Figure 5):

Qt Signals and Slots
Figure 5: Signal was triggered

 

Engr Fahad

My name is Shahzada Fahad and I am an Electrical Engineer. I have been doing Job in UAE as a site engineer in an Electrical Construction Company. Currently, I am running my own YouTube channel "Electronic Clinic", and managing this Website. My Hobbies are * Watching Movies * Music * Martial Arts * Photography * Travelling * Make Sketches and so on...

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button