Signale und Slots
Einführung
In der GUI-Programmierung möchten wir oft, dass ein anderes Widget benachrichtigt wird, wenn wir ein Widget ändern. Allgemeiner gesagt möchten wir, dass Objekte jeglicher Art miteinander kommunizieren können. Wenn ein Benutzer beispielsweise auf die Schaltfläche „ Close “ klickt, möchten wir wahrscheinlich, dass die Funktion „ close()“ des Fensters aufgerufen wird.
Andere Toolkits erreichen diese Art der Kommunikation mithilfe von Callbacks. Ein Callback ist ein Zeiger auf eine Funktion. Wenn Sie also möchten, dass eine Verarbeitungsfunktion Sie über ein bestimmtes Ereignis benachrichtigt, übergeben Sie einen Zeiger auf eine andere Funktion (den Callback) an die Verarbeitungsfunktion. Die Verarbeitungsfunktion ruft den Callback dann zum geeigneten Zeitpunkt auf. Zwar gibt es erfolgreiche Frameworks, die diese Methode verwenden, doch können Callbacks unintuitiv sein und Probleme bei der Gewährleistung der Typkorrektheit der Callback-Argumente mit sich bringen.
Signale und Slots
In Qt gibt es eine Alternative zur Callback-Technik: Wir verwenden Signale und Slots. Ein Signal wird ausgelöst, wenn ein bestimmtes Ereignis eintritt. Die Qt Widgets verfügen über viele vordefinierte Signale, aber wir können Widgets jederzeit unterklassen, um ihnen eigene Signale hinzuzufügen. Ein Slot ist eine Funktion, die als Reaktion auf ein bestimmtes Signal aufgerufen wird. Die Qt Widgets verfügen über viele vordefinierte Slots, doch es ist gängige Praxis, Widgets zu unterklassen und eigene Slots hinzuzufügen, um die Signale zu verarbeiten, die für einen von Interesse sind.
Der Mechanismus der Signale und Slots ist typsicher: Die Signatur eines Signals muss mit der Signatur des empfangenden Slots übereinstimmen. (Tatsächlich kann ein Slot eine kürzere Signatur haben als das Signal, das er empfängt, da er zusätzliche Argumente ignorieren kann.) Da die Signaturen kompatibel sind, kann uns der Compiler dabei helfen, Typkonflikte zu erkennen, wenn wir die auf Funktionszeigern basierende Syntax verwenden. Die zeichenfolgenbasierte SIGNAL- und SLOT-Syntax erkennt Typkonflikte zur Laufzeit. Signale und Slots sind lose gekoppelt: Eine Klasse, die ein Signal aussendet, weiß weder, welche Slots das Signal empfangen, noch ist es für sie von Belang. Der Signal- und Slot-Mechanismus von Qt stellt sicher, dass beim Verbinden eines Signals mit einem Slot dieser Slot zum richtigen Zeitpunkt mit den Parametern des Signals aufgerufen wird. Signale und Slots können eine beliebige Anzahl von Argumenten beliebigen Typs annehmen. Sie sind vollständig typsicher.
Alle Klassen, die von ` QObject ` oder einer ihrer Unterklassen (z. B. ` QWidget`) erben, können Signale und Slots enthalten. Signale werden von Objekten ausgesendet, wenn sie ihren Zustand auf eine Weise ändern, die für andere Objekte von Interesse sein könnte. Das ist alles, was das Objekt zur Kommunikation tut. Es weiß nicht und kümmert sich auch nicht darum, ob irgendetwas die von ihm ausgesendeten Signale empfängt. Dies ist echte Informationskapselung und stellt sicher, dass das Objekt als Softwarekomponente verwendet werden kann.
Slots können zum Empfangen von Signalen verwendet werden, sind aber auch normale Mitgliedsfunktionen. Genauso wie ein Objekt nicht weiß, ob irgendetwas seine Signale empfängt, weiß ein Slot nicht, ob Signale an ihn angeschlossen sind. Dies gewährleistet, dass mit Qt wirklich unabhängige Komponenten erstellt werden können.
Man kann so viele Signale an einen einzelnen Slot anschließen, wie man möchte, und ein Signal kann mit so vielen Slots verbunden werden, wie man benötigt. Es ist sogar möglich, ein Signal direkt mit einem anderen Signal zu verbinden. (Dadurch wird das zweite Signal sofort ausgelöst, sobald das erste ausgelöst wird.)
Zusammen bilden Signale und Slots einen leistungsstarken Mechanismus zur Komponentenprogrammierung.
Signale
Signale werden von einem Objekt ausgesendet, wenn sich dessen interner Zustand in einer Weise geändert hat, die für den Client oder Eigentümer des Objekts von Interesse sein könnte. Signale sind öffentlich zugängliche Funktionen und können von überall her ausgesendet werden; wir empfehlen jedoch, sie nur von der Klasse aus zu senden, die das Signal definiert, sowie von deren Unterklassen.
Wenn ein Signal ausgesendet wird, werden die damit verbundenen Slots in der Regel sofort ausgeführt, genau wie bei einem normalen Funktionsaufruf. Dabei ist der Signal- und Slot-Mechanismus völlig unabhängig von jeglicher GUI-Ereignisschleife. Die Ausführung des Codes, der auf die Anweisung „ emit “ folgt, erfolgt erst, nachdem alle Slots zurückgekehrt sind. Etwas anders verhält es sich bei der Verwendung von ` queued connections`; in diesem Fall wird der Code nach dem Schlüsselwort ` emit ` sofort fortgesetzt, und die Slots werden später ausgeführt.
Sind mehrere Slots mit einem Signal verbunden, werden die Slots nacheinander in der Reihenfolge ihrer Verbindung ausgeführt, sobald das Signal ausgelöst wird.
Signale werden automatisch vom moc generiert und dürfen nicht in der Datei „ .cpp “ implementiert werden.
Ein Hinweis zu den Argumenten: Unsere Erfahrung zeigt, dass Signale und Slots besser wiederverwendbar sind, wenn sie keine speziellen Typen verwenden. Würde ` QScrollBar::valueChanged()` einen speziellen Typ wie beispielsweise den hypothetischen `QScrollBar::Range` verwenden, könnte er nur mit Slots verbunden werden, die speziell für ` QScrollBar` entwickelt wurden. Das Verbinden verschiedener Eingabe-Widgets miteinander wäre dann unmöglich.
Slots
Ein Slot wird aufgerufen, wenn ein mit ihm verbundenes Signal ausgelöst wird. Slots sind normale C++-Funktionen und können wie gewohnt aufgerufen werden; ihre einzige Besonderheit besteht darin, dass Signale mit ihnen verbunden werden können.
Da Slots normale Mitgliedsfunktionen sind, gelten bei direktem Aufruf die üblichen C++-Regeln. Als Slots können sie jedoch von jeder Komponente, unabhängig von deren Zugriffsebene, über eine Signal-Slot-Verbindung aufgerufen werden. Das bedeutet, dass ein von einer Instanz einer beliebigen Klasse ausgesendetes Signal dazu führen kann, dass ein privater Slot in einer Instanz einer nicht damit verbundenen Klasse aufgerufen wird.
Man kann Slots auch als virtuell definieren, was sich in der Praxis als sehr nützlich erwiesen hat.
Im Vergleich zu Callbacks sind Signale und Slots aufgrund ihrer größeren Flexibilität etwas langsamer, obwohl der Unterschied in realen Anwendungen unerheblich ist. Im Allgemeinen ist das Aussenden eines Signals, das mit einigen Slots verbunden ist, etwa zehnmal langsamer als der direkte Aufruf der Empfänger mit nicht-virtuellen Funktionsaufrufen. Dies ist der Overhead, der erforderlich ist, um das Verbindungsobjekt zu lokalisieren, sicher alle Verbindungen zu durchlaufen (d. h. zu prüfen, dass nachfolgende Empfänger während der Signalausgabe nicht zerstört wurden) und alle Parameter generisch zu marshallieren. Zwar mögen zehn nicht-virtuelle Funktionsaufrufe nach viel klingen, doch ist der Overhead weitaus geringer als beispielsweise bei Operationen wie ` new ` oder ` delete `. Sobald Sie eine Zeichenfolgen-, Vektor- oder Listenoperation ausführen, die im Hintergrund ` new ` oder ` delete` erfordert, macht der Overhead durch Signale und Slots nur einen sehr kleinen Anteil der gesamten Kosten für Funktionsaufrufe aus. Das Gleiche gilt, wenn Sie in einem Slot einen Systemaufruf ausführen oder indirekt mehr als zehn Funktionen aufrufen. Die Einfachheit und Flexibilität des Signale-und-Slots-Mechanismus ist den Overhead mehr als wert, den Ihre Benutzer ohnehin gar nicht bemerken werden.
Beachten Sie, dass andere Bibliotheken, die Variablen namens „ signals “ oder „ slots “ definieren, beim Kompilieren zusammen mit einer Qt-basierten Anwendung zu Compiler-Warnungen und -Fehlern führen können. Um dieses Problem zu beheben, deaktivieren Sie das betreffende Präprozessorsymbol mit ` #undef `.
Ein kleines Beispiel
Eine minimale C++-Klassendeklaration könnte wie folgt lauten:
class Counter
{
public:
Counter() { m_value = 0; }
int value() const { return m_value; }
void setValue(int value);
private:
int m_value;
};Eine kleine, auf „ QObject “ basierende Klasse könnte wie folgt aussehen:
#include <QObject>
class Counter : public QObject
{
Q_OBJECT
// Note. The Q_OBJECT macro starts a private section.
// To declare public members, use the 'public:' access modifier.
public:
Counter() { m_value = 0; }
int value() const { return m_value; }
public slots:
void setValue(int value);
signals:
void valueChanged(int newValue);
private:
int m_value;
};Die auf „ QObject “ basierende Version verfügt über denselben internen Zustand und bietet öffentliche Methoden für den Zugriff auf diesen Zustand, unterstützt darüber hinaus jedoch die Komponentenprogrammierung mithilfe von Signalen und Slots. Diese Klasse kann der Außenwelt mitteilen, dass sich ihr Zustand geändert hat, indem sie ein Signal aussendet – „ valueChanged() “ – und verfügt über einen Slot, an den andere Objekte Signale senden können.
Alle Klassen, die Signale oder Slots enthalten, müssen „ Q_OBJECT “ am Anfang ihrer Deklaration angeben. Außerdem müssen sie (direkt oder indirekt) von „ QObject “ abgeleitet sein.
Slots werden vom Anwendungsprogrammierer implementiert. Hier ist eine mögliche Implementierung des Slots „ Counter::setValue() “:
void Counter::setValue(int value)
{
if (value != m_value) {
m_value = value;
emit valueChanged(value);
}
}Die Zeile „ emit “ sendet das Signal „ valueChanged() “ vom Objekt aus, wobei der neue Wert als Argument übergeben wird.
Im folgenden Codeausschnitt erstellen wir zwei „ Counter “-Objekte und verbinden das Signal „ valueChanged() “ des ersten Objekts über „ QObject::connect()“ mit dem Slot „ setValue() “ des zweiten Objekts:
Counter a, b;
QObject::connect(&a, &Counter::valueChanged,
&b, &Counter::setValue);
a.setValue(12); // a.value() == 12, b.value() == 12
b.setValue(48); // a.value() == 12, b.value() == 48Der Aufruf von ` a.setValue(12) ` bewirkt, dass ` a ` ein ` valueChanged(12) `-Signal aussendet, das von ` b ` in dessen ` setValue() `-Slot empfangen wird, d. h., ` b.setValue(12) ` wird aufgerufen. Anschließend sendet ` b ` dasselbe ` valueChanged() `-Signal aus, doch da kein Slot mit dem ` valueChanged() `-Signal von ` b` verbunden wurde, wird das Signal ignoriert.
Beachten Sie, dass die Funktion „ setValue() “ den Wert nur dann setzt und das Signal nur dann aussendet, wenn „ value != m_value “ gilt. Dies verhindert eine Endlosschleife im Falle zyklischer Verbindungen (z. B. wenn „ b.valueChanged() “ mit „ a.setValue() “ verbunden wäre).
Standardmäßig wird bei jeder hergestellten Verbindung ein Signal ausgelöst; bei doppelten Verbindungen werden zwei Signale ausgelöst. Sie können alle diese Verbindungen mit einem einzigen Aufruf von ` disconnect()` unterbrechen. Wenn Sie „ Qt::UniqueConnection “ als type übergeben, wird die Verbindung nur hergestellt, wenn es sich nicht um ein Duplikat handelt. Wenn bereits ein Duplikat vorhanden ist (genau dasselbe Signal an genau denselben Slot derselben Objekte), schlägt die Verbindung fehl und „connect“ gibt false zurück.
Dieses Beispiel veranschaulicht, dass Objekte zusammenarbeiten können, ohne Informationen übereinander zu benötigen. Um dies zu ermöglichen, müssen die Objekte lediglich miteinander verbunden werden. Dies lässt sich durch einige einfache Aufrufe der Funktion ` QObject::connect()` oder mithilfe der automatischen Verbindungsfunktion von uic erreichen.
Ein konkretes Beispiel
Im Folgenden finden Sie ein Beispiel für den Header einer einfachen Widget-Klasse ohne Member-Funktionen. Damit soll gezeigt werden, wie Sie Signale und Slots in Ihren eigenen Anwendungen nutzen können.
#ifndef LCDNUMBER_H
#define LCDNUMBER_H
#include <QFrame>
class LcdNumber : public QFrame
{
Q_OBJECTLcdNumber Sie erbt von ` QObject`, das den Großteil des Signal-Slot-Know-hows enthält, über ` QFrame ` und ` QWidget`. Es ähnelt in gewisser Weise dem integrierten Widget ` QLCDNumber `.
Das Makro ` Q_OBJECT ` wird vom Präprozessor expandiert, um mehrere Member-Funktionen zu deklarieren, die von ` moc` implementiert werden; sollten Sie Compilerfehler der Art „undefined reference to vtable for LcdNumber “ erhalten, haben Sie wahrscheinlich vergessen, den `moc` auszuführen oder die `moc`-Ausgabe in den Link-Befehl einzubeziehen.
public:
LcdNumber(QWidget *parent = nullptr);
signals:
void overflow();Nach dem Klassenkonstruktor und den Mitgliedern ` public ` deklarieren wir die Klasse ` signals`. Die Klasse ` LcdNumber ` sendet ein Signal namens ` overflow()`, wenn sie aufgefordert wird, einen unmöglichen Wert anzuzeigen.
Wenn Ihnen ein Überlauf egal ist oder Sie wissen, dass kein Überlauf auftreten kann, können Sie das Signal „ overflow() “ ignorieren, d. h. es mit keinem Slot verbinden.
Wenn Sie hingegen zwei verschiedene Fehlerfunktionen aufrufen möchten, wenn die Zahl überläuft, verbinden Sie das Signal einfach mit zwei verschiedenen Slots. Qt ruft beide auf (in der Reihenfolge, in der sie verbunden wurden).
public slots:
void display(int num);
void display(double num);
void display(const QString &str);
void setHexMode();
void setDecMode();
void setOctMode();
void setBinMode();
void setSmallDecimalPoint(bool point);
};
#endifEin Slot ist eine Empfängerfunktion, mit der Informationen über Zustandsänderungen in anderen Widgets abgerufen werden können. „ LcdNumber “ nutzt ihn, wie der obige Code zeigt, um die angezeigte Zahl festzulegen. Da „ display() “ Teil der Schnittstelle der Klasse zum Rest des Programms ist, ist der Slot öffentlich.
In mehreren Beispielprogrammen wird das Signal ` valueChanged()` eines ` QScrollBar ` mit dem Slot ` display() ` verbunden, sodass die Zahl auf dem LCD-Display kontinuierlich den Wert des Bildlaufbalkens anzeigt.
Beachten Sie, dass `display()` überladen ist. Die Signale und Slots von Qt bieten Ihnen stark typisierte Verbindungen. Sie sind zur Kompilierungszeit sicherer als herkömmliche Callbacks. Bei Callbacks müssten Sie unterschiedliche Funktionsnamen verwenden und den Typ manuell nachverfolgen. Bei überladenen Funktionen müssen Sie jedoch angeben, welche Version verwendet werden soll. Der nächste Abschnitt zeigt Ihnen, wie das geht.
Verbindung zu überladenen Signalen und Slots
Wenn Signale oder Slots überladen sind (d. h. mehrere Versionen mit unterschiedlichen Parametern haben), müssen Sie mithilfe der Funktionszeiger-Syntax explizit angeben, welche Version Sie verbinden möchten. Zur Eindeutigkeit können Sie ` qOverload()` oder ` static_cast ` verwenden:
// Connect to the QString overload of QCompleter::activated(const QString &)
connect(completer, qOverload<const QString &>(&QCompleter::activated),
this, &MyClass::onActivatedText);
// Or select QLCDNumber::display(int) when connecting from QSlider::valueChanged(int)
connect(slider, &QSlider::valueChanged,
lcd, qOverload<int>(&QLCDNumber::display));
// Using static_cast (more verbose):
connect(completer, static_cast<void(QCompleter::*)(const QString &)>(&QCompleter::activated),
this, &MyClass::onActivatedText);
// Or using a lambda to call the correct overload:
connect(slider, &QSlider::valueChanged,
this, [lcd](int value) { lcd->display(value); });Automatische Verbindungsverwaltung
Qt verwaltet automatisch die Lebensdauer von Verbindungen zwischen von ` QObject` abgeleiteten Typen. Wenn entweder das Sender- oder das Empfängerobjekt zerstört wird, wird die Verbindung automatisch entfernt, wodurch Aufrufe an gelöschte Objekte verhindert werden. Dies gilt sowohl für die Funktionszeiger-Syntax als auch für die stringbasierte SIGNAL/SLOT-Syntax.
Bei Lambda-Verbindungen muss ein Kontextobjekt (in der Regel this) angegeben werden, um sicherzustellen, dass die Lambda-Verbindung getrennt wird, wenn der Kontext zerstört wird:
connect(button, &QPushButton::clicked, this, [this]{ handleClick(); });Zwar schützt Qt vor der Signalübermittlung an vollständig zerstörte Objekte, doch können Signale während der Objektzerstörung weiterhin übermittelt werden, nachdem der Destruktor einer abgeleiteten Klasse beendet wurde, aber bevor „ ~QObject “ erreicht wird. Diese Einschränkung gilt speziell für Verbindungen, die mit der Funktionszeiger-Syntax hergestellt wurden. Dies kann auftreten, wenn ein Destruktor der Basisklasse Signale aussendet, mit denen die bereits zerstörte abgeleitete Klasse verbunden war. Erwägen Sie, solche Signale in Destruktoren explizit zu trennen, falls dies für Ihre Klasse problematisch sein könnte.
Signale und Slots mit Standardargumenten
Die Signaturen von Signalen und Slots können Argumente enthalten, und diese Argumente können Standardwerte haben. Betrachten Sie beispielsweise ` QObject::destroyed()`:
void destroyed(QObject* = nullptr);Wenn ein ` QObject ` gelöscht wird, sendet er das Signal ` QObject::destroyed()` aus. Wir möchten dieses Signal abfangen, wo immer wir eine lose Referenz auf das gelöschte ` QObject` haben, damit wir diese bereinigen können. Eine geeignete Slot-Signatur könnte wie folgt aussehen:
void objectDestroyed(QObject* obj = nullptr);Um das Signal mit dem Slot zu verbinden, verwenden wir ` QObject::connect()`. Es gibt mehrere Möglichkeiten, Signale und Slots miteinander zu verbinden. Die erste besteht darin, Funktionszeiger zu verwenden:
connect(sender, &QObject::destroyed, this, &MyObject::objectDestroyed);Die Verwendung von ` QObject::connect()` mit Funktionszeigern bietet mehrere Vorteile. Erstens kann der Compiler so überprüfen, ob die Argumente des Signals mit den Argumenten des Slots kompatibel sind. Bei Bedarf können Argumente zudem vom Compiler implizit konvertiert werden.
Sie können auch eine Verbindung zu Funktoren oder C++11-Lambdas herstellen:
connect(sender, &QObject::destroyed, this, [=](){ this->m_objects.remove(sender); });In beiden Fällen übergeben wir ` this ` als Kontext beim Aufruf von `connect()`. Das Kontextobjekt liefert Informationen darüber, in welchem Thread der Empfänger ausgeführt werden soll. Dies ist wichtig, da die Angabe des Kontexts sicherstellt, dass der Empfänger im Kontext-Thread ausgeführt wird.
Die Lambda-Funktion wird getrennt, wenn der Sender oder der Kontext zerstört wird. Sie sollten darauf achten, dass alle innerhalb des Funktors verwendeten Objekte noch vorhanden sind, wenn das Signal ausgesendet wird.
Eine weitere Möglichkeit, ein Signal mit einem Slot zu verbinden, ist die Verwendung von ` QObject::connect()` sowie der Makros ` SIGNAL ` und ` SLOT `. Die Regel dafür, ob Argumente in die Makros ` SIGNAL() ` und ` SLOT() ` aufgenommen werden sollen, wenn die Argumente Standardwerte haben, lautet: Die an das Makro ` SIGNAL() ` übergebene Signatur darf nicht weniger Argumente enthalten als die an das Makro ` SLOT() ` übergebene Signatur.
All dies würde funktionieren:
connect(sender, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed(Qbject*)));
connect(sender, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed()));
connect(sender, SIGNAL(destroyed()), this, SLOT(objectDestroyed()));Aber dies hier funktioniert nicht:
connect(sender, SIGNAL(destroyed()), this, SLOT(objectDestroyed(QObject*)));...da der Slot ein „ QObject “ erwartet, das das Signal jedoch nicht sendet. Diese Verbindung führt zu einem Laufzeitfehler.
Beachten Sie, dass die Argumente von Signal und Slot bei Verwendung dieser Überladung von ` QObject::connect()` nicht vom Compiler überprüft werden.
Erweiterte Verwendung von Signalen und Slots
Für Fälle, in denen Sie möglicherweise Informationen über den Absender des Signals benötigen, stellt Qt die Funktion ` QObject::sender()` zur Verfügung, die einen Zeiger auf das Objekt zurückgibt, das das Signal gesendet hat.
Lambda-Ausdrücke sind eine bequeme Möglichkeit, benutzerdefinierte Argumente an einen Slot zu übergeben:
connect(action, &QAction::triggered, engine,
[=]() { engine->processAction(action->text()); });Verwendung von Qt mit Signalen und Slots von Drittanbietern
Es ist möglich, Qt mit einem Signal-/Slot-Mechanismus von Drittanbietern zu verwenden. Sie können sogar beide Mechanismen im selben Projekt nutzen. Dazu fügen Sie Folgendes in Ihre CMake-Projektdatei ein:
target_compile_definitions(my_app PRIVATE QT_NO_KEYWORDS)In einer qmake-Projektdatei (.pro) müssen Sie Folgendes eintragen:
CONFIG += no_keywordsDadurch wird Qt angewiesen, die moc-Schlüsselwörter „ signals “, „ slots “ und „ emit “ nicht zu definieren, da diese Namen von einer Bibliothek eines Drittanbieters, z. B. Boost, verwendet werden. Um Qt-Signale und -Slots mit dem Flag „ no_keywords “ weiterhin verwenden zu können, ersetzen Sie einfach alle Verwendungen der Qt-moc-Schlüsselwörter in Ihren Quelldateien durch die entsprechenden Qt-Makros „ Q_SIGNALS “ (oder „ Q_SIGNAL “) „ Q_SLOTS “ (oder „ Q_SLOT “) und „ Q_EMIT “.
Signale und Slots in Qt-basierten Bibliotheken
Die öffentliche API von Qt-basierten Bibliotheken sollte die Schlüsselwörter „ Q_SIGNALS “ und „ Q_SLOTS “ anstelle von „ signals “ und „ slots “ verwenden. Andernfalls ist es schwierig, eine solche Bibliothek in einem Projekt zu verwenden, das „ QT_NO_KEYWORDS “ definiert.
Um diese Einschränkung durchzusetzen, kann der Bibliotheksentwickler beim Erstellen der Bibliothek die Präprozessor-Definition QT_NO_SIGNALS_SLOTS_KEYWORDS setzen.
Diese Definition schließt Signale und Slots aus, ohne die Verwendung anderer Qt-spezifischer Schlüsselwörter in der Bibliotheksimplementierung zu beeinträchtigen.
Siehe auch „ QLCDNumber“ , „ QObject::connect()“, „Meta-Objekt-System“ und „Qt-Eigenschaftssystem“.
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.