qt – emit a signal

When you trying to link the slots and signals together you need to have a QObject::connect and also a emitting, I have created a basic demonstration of this with a QPushButton (link to qt signal and slots, and a QT link for the signal and slots)

The basics of slot(s) and signal(s) with emit(ting) is that a slot is where the emit(ed) signal goes to, when a signal is emit(ed) via a class. For example if you want to link a value changed event then you would emit a signal from within the class and then use that signal with the QObject::connect to link to a slot within class as well.

I have created a class called EmitterTest that has a function within it called

        void setValueAndEmit(int v);

this function will set the value and emit the signal for any QObject::connect to link to a slot. To emit the signal you just

        emit valueChanged(v);

where the valueChanged is the signal within the class definition (you do not define that function because it is kinder like a virtual function).

To allow for these slots and signals to be defined within the class you need to call the macro Q_OBJECT at the top of the class (within a private area) so that all of the necessary attachments to the class can be created (within the moc file associated with the class when you run the qmake later on).

To define a signal and slot there is keywords within the “new” class structure available because of the Q_OBJECT and you can just use them like public and private declarations

    public slots :
        void setValue(int v);
 
    signals:
        void valueChanged(int newV);

signals are always public in there access rights.

What the code below does is to create a slot and signal with a function that will emit a signal when called (the function that is) so the signal is “fired” off to what ever is listening to it, to connect a signal to a slot you use the QObject::connect as below

    EmitterTest em1, em2;
 
    QObject::connect(&em1, SIGNAL(valueChanged(int)),
                     &em2, SLOT(setValue(int)));

where the EmitterTest is the class that I am creating, and the object em1 signal valueChanged is linked to the same class type but different instance of it, em2 slot setValue.

Here is the code below for the full EmitterTest, here is the header file for the emitting test class, if you save as emitting.h

#ifndef EMITTING_H
#define EMITTING_H
 
#include <QObject>
 
class EmitterTest : public QObject
{
    Q_OBJECT
 
    public:
        EmitterTest() { mem_value = 0;}
 
        int getValue() const { return mem_value;}
        void setValueAndEmit(int v);
 
    // these pick up the emitted signal
    public slots :
        void setValue(int v);
 
    // these are what are sent out over emitted signals
    // you do not implement the signals since they are just virtual functions
    // as such that you call with emit then the value within the parameter(s)
    // is passed to the slot.
    signals:
        void valueChanged(int newV);
 
    private:
        int mem_value;
};
 
#endif // EMITTING_H

and here is the emitting.cpp file, that holds the main runtime main function.

#include <QObject>
#include <QString>
#include <stdio.h>
#include "emitting.h"
 
void EmitterTest::setValue(int v)
{
    // if the value has changed
    printf("The new value for %d\n", v);
    mem_value = v;
}
 
void EmitterTest::setValueAndEmit(int v)
{
    // if the value has changed
    if (v != mem_value)
    {
        mem_value = v;
        emit valueChanged(v);
    }
}
 
int main()
{
    EmitterTest em1, em2;
 
    QObject::connect(&em1, SIGNAL(valueChanged(int)),
                     &em2, SLOT(setValue(int)));
 
    em1.setValueAndEmit(10);
    printf("The connection from the object connection em1 %d should equal em2 %d \n", em1.getValue(), em2.getValue());
    em2.setValueAndEmit(15);
    printf("The connection from the object connection em1 %d should NOT equal em2 %d \n", em1.getValue(), em2.getValue());
    // the values are not the same because I have not connected them even though I have called the emit within the
    // setValueAndEmit
    return 0;
}

if you save them into a directory and then to compile you need to have the qmake and also make (nmake for windows) to make the relevant files to build a qt project. The qmake project creates the necessary .pro file to build the project, the qmake will build the necessary files (moc files) for the make (or nmake) to build the project into a executable file

qmake -project
qmake
make

and then there will be a executable file within that directory and the output will be once you have run it

The new value for 10
The connection from the object connection em1 10 should equal em2 10
The connection from the object connection em1 10 should NOT equal em2 15

as you notice since I only connected em1 signal to em2, if you change em2 mem_value then em1 does not change as well because the em2 signal is not linked back to the em1 slot.

If you get this error when you are trying out any emit test

undefined reference to `vtable for --- your class name

, it is because for some reason if you use the Q_OBJECT you need to define the class within a .h (header file) and then it will compile instead if you try and use the same .cpp for the main source code then you will get this error message.

QT – hello world – signals and slots

QT framework is a great application stack that allows for cross development (between different OS’s) without having to re-do the code for e.g.Linux/Windows different setups. It is similar to Java and C Sharp (C#) in that way, but the difference with them is that they compile into a native object which can then run within a virtual machine where as the QT framework is more designed to be compiled within each setup, which should make it quicker as well because it will be in the native code and not running in a virtual machine.

The nice thing about QT is that it has its own SIGNAL and SLOTS, similar to C Sharp (C#) events process where you can link something happening to when something else has just happened (e.g. moved a value on a slider bar and a integer value alters as well).

I shall go into more detail with SIGNAL’s and SLOT’s in the next tutorial for QT development, but in essence they are defined within the class of the object itself and then you link them with a “connect” syntax. e.g.

    object::connect(object_to_send_signal, SIGNAL(signal_of_the_object_that_will_be_emit),
                        object_to_pick_up_signal, SLOT(function_to_call_once_signal_has_been_emitted));

so you will link/connect a objects that sends a signal to a slot that receives the signal.

Here is a basic GUI for a QT application that will have a button that says “QUIT” and also a signal that is emitted once that button class clicked() has happened, that links to the application (QApplication object) that has a “quit” function that stops the program from executing.

To start with we first include the basic header files and then create a QApplication (the gui as such) and then a QPushButton object with the default text being “Quit”.

    QApplication app(argc, argv);
    QPushButton *button = new QPushButton("Quit");

once this has happened we then create the connection between the clicking of the button to the application “quit”ing function.

    QObject::connect(button, SIGNAL(clicked()),
                        &app, SLOT(quit()));

we have only created the button but not placed it on the screen, so we use the show method within the button class and then run the application execution function to actually run the GUI program

    button->show();
    return app.exec();

if you save this file within a directory called quit and call this file quit.cpp

#include <QApplication>
#include <QPushButton>
 
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QPushButton *button = new QPushButton("Quit");
    QObject::connect(button, SIGNAL(clicked()),
                        &app, SLOT(quit()));
    button->show();
    return app.exec();
}

then change to that directory within your console/command line and then we need to build up the QT compiling project files.

qmake -project

this will make the quit.pro file within that same directory (it uses the same name as the directory name), and within that file is

######################################################################
# Automatically generated by qmake (2.01a) Wed Feb 24 11:49:39 2010
######################################################################
 
TEMPLATE = app
TARGET =
DEPENDPATH += .
INCLUDEPATH += .
 
# Input
SOURCES += quit.cpp

which basically means that the application uses the source files of quit.cpp, you then need to create the Makefile (which is the actual compiling c++ file that g++ uses to create the application)

qmake

so the directory will be something similar to

Makefile  
quit.cpp
quit.pro

within Linux you can just now run the make command which will make the application “quit” but without windows you would need to have the nmake command instead, so run either make or nmake and within the directory now will be a quit application that you can run and the output would be a simple GUI with a button on it that says “Quit” and once you click that button the application will quit.