Qt Signal Slot Between Classes

Signal

making changes in one component trigger behavior in another. You can trigger behaviors in response to user input, such as button presses or text input, or events in your own code.SearchComments: signalTags:Video: 337608027/137c732675Duration: 10IsPremium: TrueCollection: startCollectionIndex: 1

Qt 5 continues to support the old string-based syntax for connecting signals and slots defined in a QObject or any class that inherits from QObject (including QWidget) connect (sender, SIGNAL (valueChanged (QString, QString)), receiver, SLOT (updateValue (QString))); New: connecting to QObject member. Hi, I want to create a connection between a signal and slot, which are in different classes. @Mogli123 said in signal slot between 2 classes: // I'm not shure how to do that. I'm very new in cpp and qt and don't know how to solve that problem. Can you give me a small example please?

Build complex application behaviors using signals and slots, and override widget event handling with custom events.

As already described, every interaction the user has with a Qt application causes an Event. There are multiple types of event, each representing a difference type of interaction — e.g. mouse or keyboard events.

Events that occur are passed to the event-specific handler on the widget where the interaction occurred. For example, clicking on a widget will cause a QMouseEvent to be sent to the .mousePressEvent event handler on the widget. This handler can interrogate the event to find out information, such as what triggered the event and where specifically it occurred.

You can intercept events by subclassing and overriding the handler function on the class, as you would for any other function. You can choose to filter, modify, or ignore events, passing them through to the normal handler for the event by calling the parent class function with super().

However, imagine you want to catch an event on 20 different buttons. Subclassing like this now becomes an incredibly tedious way of catching, interpreting and handling these events.

python

Thankfully Qt offers a neater approach to receiving notification of things happening in your application: Signals.

Signals

Instead of intercepting raw events, signals allow you to 'listen' for notifications of specific occurrences within your application. While these can be similar to events — a click on a button — they can also be more nuanced — updated text in a box. Data can also be sent alongside a signal - so as well as being notified of the updated text you can also receive it.

The receivers of signals are called Slots in Qt terminology. A number of standard slots are provided on Qt classes to allow you to wire together different parts of your application. However, you can also use any Python function as a slot, and therefore receive the message yourself.

Load up a fresh copy of `MyApp_window.py` and save it under a new name for this section. The code is copied below if you don't have it yet.

Basic signals

First, let's look at the signals available for our QMainWindow. You can find this information in the Qt documentation. Scroll down to the Signals section to see the signals implemented for this class.

Qt 5 Documentation — QMainWindow Signals

As you can see, alongside the two QMainWindow signals, there are 4 signals inherited from QWidget and 2 signals inherited from Object. If you click through to the QWidget signal documentation you can see a .windowTitleChanged signal implemented here. Next we'll demonstrate that signal within our application.

Qt 5 Documentation — Widget Signals

The code below gives a few examples of using the windowTitleChanged signal.

python

Try commenting out the different signals and seeing the effect on what the slot prints.

We start by creating a function that will behave as a ‘slot’ for our signals.

Then we use .connect on the .windowTitleChanged signal. We pass the function that we want to be called with the signal data. In this case the signal sends a string, containing the new window title.

If we run that, we see that we receive the notification that the window title has changed.

Events

Next, let’s take a quick look at events. Thanks to signals, for most purposes you can happily avoid using events in Qt, but it’s important to understand how they work for when they are necessary.

Qt Signal Slot Between Classes

As an example, we're going to intercept the .contextMenuEvent on QMainWindow. This event is fired whenever a context menu is about to be shown, and is passed a single value event of type QContextMenuEvent.

To intercept the event, we simply override the object method with our new method of the same name. So in this case we can create a method on our MainWindow subclass with the name contextMenuEvent and it will receive all events of this type.

If you add the above method to your MainWindow class and run your program you will discover that right-clicking in your window now displays the message in the print statement.

Sometimes you may wish to intercept an event, yet still trigger the default (parent) event handler. You can do this by calling the event handler on the parent class using super as normal for Python class methods.

python

This allows you to propagate events up the object hierarchy, handling only those parts of an event handler that you wish.

However, in Qt there is another type of event hierarchy, constructed around the UI relationships. Widgets that are added to a layout, within another widget, may opt to pass their events to their UI parent. In complex widgets with multiple sub-elements this can allow for delegation of event handling to the containing widget for certain events.

However, if you have dealt with an event and do not want it to propagate in this way you can flag this by calling .accept() on the event.

Alternatively, if you do want it to propagate calling .ignore() will achieve this.

python

In this section we've covered signals, slots and events. We've demonstratedsome simple signals, including how to pass less and more data using lambdas.We've created custom signals, and shown how to intercept events, pass onevent handling and use .accept() and .ignore() to hide/show eventsto the UI-parent widget. In the next section we will go on to takea look at two common features of the GUI — toolbars and menus.

  • DESCRIPTION
  • INTERFACE

Class::Std::Slots - Provide signals and slots for standard classes.

This document describes Class::Std::Slots version 0.31

Conventionally the ways in which objects of different classes can interact with each other is designed into those classes; changes to that behaviour require either changes to the classes in question or the creation of subclasses.

Signals and slots allow objects to be wired together dynamically at run time in ways that weren't necessarily anticipated by the designers of the classes. For example consider a class that manages time consuming downloads:

For a particular application it might be desirable to be able to display a progress report as the download progresses. Unfortunately My::Downloader isn't wired to allow that. We could improve My::Downloader by providing a stub function that's called periodically during a download:

Then we could subclass My::Downloader::Better to update a display:

That's not bad - but we had to create a subclass - and we'd have to arrange for it to be created instead of a My::Downloader::Better anytime we want to use it. If displaying the progress involved updating a progress bar in a GUI we'd need to embed a reference to the progress bar in each instance of My::Downloader::Verbose.

Instead we could extend My::Downloader::Better to call an arbitrary callback via a supplied code reference each time progress() was called ... but then we have to implement the interface that allows the callback to be defined. If we also want notifications of retries and server failures we'll need still more callbacks. Tedious.

Or we could write My::Downloader::Lovely like this:

and use it like this:

That behaves just like the original My::Downloader example. Now let's hook up the progress display - we're using an imaginary GUI toolkit:

We didn't have to subclass or modify My::Downloader::Lovely and we didn't have to clutter its interface with methods to allow callbacks to be installed.

Each signal can be connected to many slots simultaneously; perhaps we want some debug to show up on the console too:

Each slot can either be a subroutine reference or an object reference and method name. Anonymous slots are particularly useful for debugging but they also provide a lightweight way to extend the behaviour of an existing class.

Only classes that emit signals need use Class::Std::Slots - any method in any class can be used as a slot.

Signals?

The signals we refer to here are unrelated to operating system signals. That's why the class is called Class::Std::Slots instead of Class::Std::Signals.

Further reading

Sarah Thompson has produced a generic signals and slots library for C++:

The accompanying documentation includes an excellent exploration of the benefits of signals and slots.

Qt (C++ again) uses signals and slots extensively. Consult the Qt documentation and in particular the section on signals and slots for more information:

Other UI toolkits including NextStep / Cocoa / GNUStep use mechanisms similar to signals and slots in all but name.

Class::Std::Slots is designed to be used in conjunction with Class::Std. It may work with classes not based on Class::Std but this is untested. To use it add use Class::Std::Slots just after use Class::Std

and add a call to signals to declare any signals your class will emit.

Class::Std::Slots will add five public methods to your class: signals, connect, disconnect, has_slots and emit_signal.

Methods created automatically

The following subroutines are installed in any class that uses the Class::Std::Slots module.

signals( signals )

Declare the list of signals that a class can emit. Multiple calls to signals are allowed but each signal should be declared only once. It is an error to redeclare a signal even in a subclass or to declare a signal with the same name as a method.

Once declared signals may be called as members of the declaring class and any subclasses. To emit a signal simply call it:

Any arguments passed to the signal will be passed to any slots registered with it. Signals never have a return value - any return values from slots are silently discarded.

connect($sig_name, ...)

Create a connection between a signal and a slot. Connections are made between objects (i.e. class instances) rather than between classes. To connect the signal started to a slot called show_status do something like this:

Whenever $my_thing emits startedshow_status will be called with any arguments that were passed to started.

To call a non-member subroutine (which may be an anonymous subroutine or closure) do this:

Anonymous subroutines are also useful to patch up impedence mismatches between the slot method and the signal. For example if the signal progress is called with two arguments (the current progress and the expected total) but the desired slot show_progress expects to be passed a percentage use something like this:

A slot may be connected to multiple signals at the same time by passing an array reference in place of the signal name:

Normally a slot is passed exactly the arguments that were passed to the signal - so when $this_obj->some_signal has been connected to $that_obj->some_slot emitting the signal like this:

will cause some_slot to be called like this:

Sometimes it is useful to be able to write generic slot functions that can be connected to many different signals and that are capable of interacting with the object that emitted the signal. The reveal_source option modifies the argument list of the slot function so that the first argument is a reference to a hash that describes the source of the signal:

When $this_obj->first_signal is emitted $generic->smart_slot will be called with this hash ref as its first argument:

When $this_obj->second_signal is emitted the hash will look like this:

Note that the options hash passed to connect is passed to the slot. This is so that additional user defined options can be used to influence the behaviour of the slot function.

The options recognised by connect itself are:

reveal_source

Modify slot arg list to include a hash that describes the source of the signal.

strong

Normally the reference to the object containing the slot method is weakened (by calling Scalar::Util::weaken on it). Set this option to make the reference strong - which means that once an object has been connected to no other references to it need be kept.

Anonymous subroutine slots are always strongly referred to - so there is no need to specify the strong option for them.

undeclared

Allow a connection to be made to an undefined signal. It is possible for an object to emit arbitrary signals by calling emit_signal. Normally connect checks that a signal has been declared before connecting to it (bugs caused by slightly misnamed signals are particularly frustrating). This flag overrides that check and makes it your responsibility to get the signal name right.

disconnect($sig_name, ...)

Break signal / slot connections. All connections are broken when the signalling object is destroyed. To break a connection at any other time use:

To break all connections from a signal to slots in a particular object use:

To break all connections for a particular signal use:

And finally to break all connections from a signalling object:

Classes

In other words each additional argument increases the specificity of the connections that are targetted.

As with connect a reference to an array of signal names may be passed:

Note that it is not possible to disconnect an anonymous slot subroutine without disconnecting all other slots connected to the same signal:

If this proves to be an enbearable limitation I'll do something about it.

emit_signal($sig_name, ...)

It's not always possible to pre-declare all the signals an object may emit. For example an XML processor may emit signals corresponding to the names of tags in the parsed XML; in that case it would be overly restrictive to require pre-declaration of the signals.

To emit an arbitrary signal - which may or may not have been declared - call emit() directly like this:

Pass connect the undeclared option to connect to an undeclared signal.

Multiple signals may be emitted at the same time (or rather one after another) by passing a reference to an array of signal names:

has_slots($sig_name)

In cases where emitting a signal involves costly computation has_slots can be called to check whether a signal has any connected slots and if not skip both the expensive computation and the signal call.

Note that there is no benefit in guarding simple signal calls with a call to has_slots:

As usual a reference to an array of signal names may be passed in which case has_slots will return a true value if any of the named signals has connected slots.

Invalid signal name '%s'

Signal names have the same syntax as identifier names - you've tried to use a name that contains a character that isn't legal in an identifier.

Signal name must be a scalar or an array reference

Either pass a single signal name like this:

Or pass a reference to an array of signal names like this:

This applies to all methods that accept a signal name.

Signal '%s' undefined

Signals are declared by calling the signals subroutine. You're attempting to connect to an undefined signal.

Signal '%s' must be invoked as a method

Signals are fired using normal method call syntax. To fire a signal do something like

Attempt to re-enter signal '%s'

Signals are not allowed to fire themselves directly or indirectly. This is an intentional limitation. The ease with which signals can be connected to slots in complex patterns makes it easy to introduce unintended loops of mutually triggered signals.

Usage: $source->connect($sig_name, $dst_obj, $dst_method [, { options }])

connect can be called either like this:

or like this:

In either case an anonymous hash containing options may be passed as an additional argument.

Slot '%s' not handled by %s

You're attempting to connect to a slot that isn't implemented by the target object. Slots are normal member functions.

disconnect must be called as a member

Disconnect should be called like this:

or like this:

or like this:

or like this:

Signal '%s' aready declared

You're attempting to declare a signal that already exists. This may be because it has been declared as a signal or because the signal name clashes with a method name.

Note that it is illegal to redeclare a signal in a subclass if a parent already declares the signal. Since signals can't be declared to do anything other than be a signal it makes no sense to redeclare a signal in a subclass.

Class::Std::Slots requires no configuration files or environment variables.

Class::Std

Only known to work in conjuction with Class::Std. Only tested when used with Class::Std in the way shown in this document.

No bugs have been reported.

Connecting the same slot to a signal multiple times actually makes multiple connections and therefore invokes the slot as many times as it was registered when the signal is emitted. Arguably only one connection to each slot should be allowed. Let me know.

There is currently no way to disconnect an anonymous sub slot without also disconnecting other slots from the same signal.

Qt Signal Slot Between Classes Using

Class::Std::Slots replaces the DESTROY sub injected into the caller's namespace by Class::Std and arranges to call the original destructor after doing its own cleanup. This may interact badly with other modules that also replace the Class::Std destructor - although it is designed to ensure it always calls whatever destructor it finds. Suggestions for a neater way of chaining our destructor gratefully received.

I'm not sure that the code that prevents signals from re-entering (i.e. it's an error to emit a signal if that signal is already being handled) might not prevent some (fairly complex) techniques. If this proves to be a limitation in practice it would be possible to add an option to each connection that would allow that connection to be re-entrant.

Please report any bugs or feature requests to bug-class-std-slots@rt.cpan.org, or through the web interface at http://rt.cpan.org.

Andy Armstrong <andy@hexten.net>

Copyright (c) 2006, Andy Armstrong <andy@hexten.net>. All rights reserved.

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic.

BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE 'AS IS' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

Qt Signal And Slots

To install Class::Std::Slots, copy and paste the appropriate command in to your terminal.

For more information on module installation, please visit the detailed CPAN module installation guide.