Menu
Home
Log in / Register
 
Home arrow Computer Science arrow Learn BlackBerry 10 App Development
< Prev   CONTENTS   Next >

Signals and Slots

In Cascades terminology, event handling is done using signals and slots, which are basically a loosely coupled notification mechanism between controls. Whenever something interesting happens to a control, such as a state change, a predefined signal is emitted for notifying that change. If you're interested in receiving that notification, then you have to specify some application logic in JavaScript or C++, which will be called in the corresponding Cascades predefined signal handler. Signals and slots are part of the QtCore module. The Cascades framework uses them in order to build a

high-level event handling mechanism. This section will expand on the topic in order to give you a firm grip on the way signals and slots work. As noted previously, the most important property of signals is their ability to let you bind objects together without them knowing about each other.

Signals and Slots in QML

For a given predefined signal signal, Cascades also provides a corresponding predefined onSignal handler (which is also called equivalently a slot). You can write JavaScript code in your QML document to tell Cascades what to do when the handler is triggered and how the control should respond to the signal. For example, in order to handle the slider's position updates, Cascades defines a predefined onImmediateValueChanged signal handler called when the slider emits the immediateValueChanged signal. In Listing 1-1, the predefined handler will execute the texfield.text = Math.round(immediateValue) JavaScript code in order to update the textfield. You will also notice that the JavaScript code references an immediateValue parameter. Signals usually include extra parameters that provide additional information about them. In QML, they are implicitly available to the JavaScript execution context and you can use them in order to retrieve further information about the change that just occurred.

You can refer to the Cascades API reference found at developer.blackberry.com/cascades/ reference/user_interface.html for a list of all predefined signals and corresponding slots organized by GUI control. Look under the core controls section.

Signals and Slots in C++

Looking at Listing 1-2, you will notice that I've used the slots: annotation to declare an

onImmediateValueChanged(float value) slot in the application delegate class. In Listing 1-3,

I've connected the slider's onImmediateValueChanged(float value) to the application delegate's onImmediateValueChanged(float value) slot using the QObject::connect(source, SIGNAL(signal), destination, SLOT(slot)) method.

Signals and slots are implemented in Qt using the following constructs:

n A class must inherit from QObject.

n You must add the Q_OBJECT macro at the beginning of the class definition. The Q_OBJECT macro marks the class as managed by the Meta Object Compiler (MOC). During compilation, the MOC generates additional code for the class in a file called moc_classname.cpp, which adds support for signals and slots, metaprogramming, and other features for runtime introspection. Note that the entire process is completely transparent and you don't need to worry about it during compilation.

n You must declare the class signals using the signals: annotation.

n You must declare the class slots using the slots: annotation.

n You must define the class slots as regular member functions.

n Finally, you must wire signals and slots using QObject::connect().

As an example, let us consider the case of a temperature sensor. We would like to build a system where we can chart and log temperature readings over time. We would also want to decouple the system by separating the charting logic from the temperature logging. A very simplified design can be implemented using three classes (see Figure 1-3). The TempSensor class is responsible for the temperature readings through the setTemp(float newValue) function, which could be triggered by a hardware interrupt. The function would then update TempSensor's internal state, and then emit a tempChanged(float) signal. The TempChart and TempLogger classes would respectively handle the signal with a corresponding onTempChanged(float) slot.

Figure 1-3. Sensor system

The C++ implementation is given in Listings 1-4 and 1-5.

Listing 1-4. TempSensor.hpp

#include <QObject>

class TempSensor : public QObject{

Q_OBJECT

public:

TempSensor(QObject* parent=0) : QObject(parent), m_value(0) {}; virtual ~TempSensor(){};

voidsetTemp(float newValue){ if(m_value == newValue) return; m_value = newValue; emit(tempChanged(m_value);

}

signals:

void tempChanged(float)

private:

float m_value;

};

#include <QObject>

class TempChart : public QObject{

Q_OBJECT

public:

TempChart(QObject* parent=0) : QObject(parent){}; public slots:

void onTempChanged(float value){

// do charting

}

};

#include <QObject>

class TempLogger : public QObject{

Q_OBJECT

public:

TempLogger(QObject* parent=0) : QObject(parent){};

public slots:

void onTempChanger(float value){

// do logging

}

};

Listing 1-5. main.cpp

#include "TempSensor.hpp" int main(){

TempSensor sensor; TempLogger logger; TempChart chart;

QObject::connect(sensor, SIGNAL(tempChanged(float)), logger, SLOT(onTempChanged(float))); QObject::connect(sensor, SIGNAL(tempChanged(float)), chart, SLOT(onTempChanged(float)));

// do temperature readings here.

}

Here are a few things to keep in mind when implementing signals and slots:

n Signals are triggered in your code using the emit signalName() syntax (see Listing 1-4).

n Signals must always have a void return value. In other words, you can't get a return value from a signal once it has been emitted.

n As illustrated in the previous example, one signal can be connected to many slots. When the signal is emitted, the slots are called one after the other.

n The opposite is also true; many signals can be connected to the same slot.

n You can also connect a signal to another signal. When the first signal is emitted, the second one is also emitted.

n Slots are normal member functions. You can call them directly if you wish. They can also be virtual functions if you wish.

n The signature of a signal must match the signature of the receiving slot.

A slot can also have a shorter signature than the signal (in this case the slot drops the extra arguments).

Meta-Object System

Qt extends C++ with a meta-object system in order to introduce runtime introspection features that would not be available with a statically compiled language such as C++. Behind the scenes, Qt uses the meta-object compiler (MOC) to generate the extra C++ plumbing code for the functions declared by the Q_OBJECT macro and for the class signals. Finally, the QObject::connect function uses the MOC-generated introspection functions to wire signals and slots together. When building Cascades applications, the MOC is called transparently by the build system.

 
Found a mistake? Please highlight the word and press Shift + Enter  
< Prev   CONTENTS   Next >
 
Subjects
Accounting
Business & Finance
Communication
Computer Science
Economics
Education
Engineering
Environment
Geography
Health
History
Language & Literature
Law
Management
Marketing
Philosophy
Political science
Psychology
Religion
Sociology
Travel