CopperSpice API
1.9.2
|
A key aspect of a well designed GUI program involves responding to actions taken by the user of the software.
If a user clicks a close button they probably want to close the corresponding window. Since this is a common occurrence a GUI library should have a convenient mechanism to associate actions taken by the user to some process the program should take. In the case of the mouse click action the program should respond by closing the desired window.
Some programs or libraries accomplish this by using callbacks, which is a pointer to a function. With callbacks, when something happens an event handler will use the callback pointer to invoke the callback function. Callbacks can have fundamental limitations and are not the best solution for a C++ GUI program.
A more effective approach than callbacks is the mechanism provided by Signals and Slots. In this paradigm a signal is emitted when a particular event occurs. A slot is usually a method and will be called in response to the signal. The signal / slot mechanism in CopperSpice is type safe and works across threads. A signal is emitted when a particular action occurs, such as the mouse click. A slot is the response which is usually a call to a method or function.
The signal can be designed to emit any number of parameters of any copyable data type. The slot can ignore any or all of these arguments. The only constraint is that if the slot needs to receive some of the arguments the order must match those emitted by the signal. A class which emits a signal does not need to know which slots receive the signal. All classes which inherit from QObject or one of its subclasses may contain signals and slots.
Using the connect() method, an application can connect a one given signal to multiple slots. It can also connect multiple signals to a single slot. Signals and slot are often connected and disconnected multiple times in response to the user input.
The disconnect() method which breaks the signal / slot relationship. There are multiple overloads and several which can be used to disconnect all existing connections which match certain criteria.
The following example shows how to declare a class which contains a signal and a slot. The CS_SIGNAL() and CS_SLOT() macros are used to declare and register the method names and parameters with the CopperSpice meta object system.
The CS_SLOT() macro is only required if your application is going to look up the slot at run time, using a string. If this is not required, simply declare the slot as you would declare any other C++ method. When the slot macro is not used then a method pointer, function pointer, or lambda expression must be used when setting up in the signal/slot connection.
Classes which contain the CS_SIGNAL or CS_SLOT macros must contain the CS_OBJECT(<class_name>) macro at the top of the class declaration. Your class must also inherit either directly from QObject or from a class which inherits from QObject.
When the value changes in Counter the valueChanged() signal will be emitted and any slot methods connected to this signal will be invoked. In this example there are two Counter objects and when the value is changed in object A the slot method will change the value in object B to match the value in Object A.
The following code will connect the signal in object A to the slot in object B.
A slot is nothing more than a normal method. The following is an implementation of the Counter::setValue()
slot.
When a signal is emitted any connected slots are normally invoked immediately.
There is a parameter in the connect() method which can be used to specify the connection type. The default is Qt::AutoConnection which usually means the same as Qt::DirectConnection and the slot will be invoked with no delay. If there are multiple slots connected to one signal the slots will be invoked in the order they were connected.
Another option is to specify Qt::QueuedConnection. This is used when the sender and receiver belong to different threads.
A slot can be a normal class method, global function, lambda expression, or function object.
In the following example the Counter class declaration has changed slightly depending on how the slot is called.
Any class which inherits from QObject will contain a meta object. The staticMetaObject() contains the class name and all signal and slot method names. This information can be useful when writing a plugin.
Refer to Meta Object System for more information.