Qt WebChannel JavaScript-API

Einrichten der JavaScript-API

Um mit QWebChannel oder WebChannel zu kommunizieren, muss ein Client die von qwebchannel.js bereitgestellte JavaScript-API verwenden und einrichten. Für Clients, die innerhalb von Qt WebEngineausgeführt werden, können Sie die Datei über qrc:///qtwebchannel/qwebchannel.js laden. Für externe Clients müssen Sie die Datei auf Ihren Webserver kopieren. Anschließend instanziieren Sie ein QWebChannel Objekt und übergeben ihm ein Transportobjekt und eine Callback-Funktion, die aufgerufen wird, sobald die Initialisierung des Kanals abgeschlossen ist und die veröffentlichten Objekte verfügbar sind. Ein optionales drittes Argument enthält ein Array von Konverter-Wrapper-Funktionen oder eine einzelne Funktion.

Das Transportobjekt implementiert eine minimale Schnittstelle zur Nachrichtenübermittlung. Es sollte ein Objekt mit einer send() -Funktion sein, die eine stringifizierte JSON-Nachricht entgegennimmt und sie an das serverseitige QWebChannelAbstractTransport -Objekt weiterleitet. Außerdem sollte seine onmessage Eigenschaft aufgerufen werden, wenn eine Nachricht vom Server empfangen wurde. Alternativ können Sie auch einen WebSocket verwenden, um die Schnittstelle zu implementieren.

Beachten Sie, dass das JavaScript QWebChannel Objekt konstruiert werden sollte, sobald das Transportobjekt voll funktionsfähig ist. Im Falle eines WebSockets bedeutet dies, dass Sie QWebChannel im onopen Handler des Sockets erstellen sollten. Schauen Sie sich das Qt WebChannel Standalone-Beispiel an, um zu sehen, wie das gemacht wird.

Hinweis: Es kann nur ein einziges QWebChannel Objekt pro Transport auf derselben Seite erstellt werden.

Eine Konverter-Wrapper-Funktion ist entweder eine Zeichenkette mit dem Namen eines eingebauten Konverters oder eine benutzerdefinierte Funktion, die das zu verarbeitende Objekt als Argument nimmt und den resultierenden Typ oder undefiniert zurückgibt, wenn die Funktion nicht anwendbar ist. Wird ein undefinierter Wert zurückgegeben, wird der nächste Konverter verarbeitet. Wenn es keine Konverter gibt, die einen anderen Wert als undefiniert zurückgeben, wird die Verarbeitung normal fortgesetzt. "Datum" ist die einzige derzeit eingebaute Konverterfunktion. Sie nimmt einen String mit einem ISO 8601-Datum und gibt ein neues Date-Objekt zurück, wenn die Syntax stimmt und das Datum gültig ist.

Interaktion mit QObjects

Sobald der an das Objekt QWebChannel übergebene Callback aufgerufen wird, ist die Initialisierung des Kanals abgeschlossen und alle veröffentlichten Objekte sind für den HTML-Client über die Eigenschaft channel.objects zugänglich. Nehmen wir also an, dass ein Objekt mit dem Bezeichner "foo" veröffentlicht wurde, dann können wir damit interagieren, wie im folgenden Beispiel gezeigt. Beachten Sie, dass die gesamte Kommunikation zwischen dem HTML-Client und dem QML/C++-Server asynchron ist. Die Eigenschaften werden auf der HTML-Seite zwischengespeichert. Außerdem ist zu beachten, dass nur QML/C++-Datentypen, die in JSON konvertiert werden können, korrekt (de-)serialisiert werden und somit für HTML-Clients zugänglich sind.

new QWebChannel(yourTransport, function(channel) {

    // Connect to a signal:
    channel.objects.foo.mySignal.connect(function() {
        // This callback will be invoked whenever the signal is emitted on the C++/QML side.
        console.log(arguments);
    });

    // To make the object known globally, assign it to the window object, i.e.:
    window.foo = channel.objects.foo;

    // Invoke a method:
    foo.myMethod(arg1, arg2, function(returnValue) {
        // This callback will be invoked when myMethod has a return value. Keep in mind that
        // the communication is asynchronous, hence the need for this callback.
        console.log(returnValue);
    });

    // Read a property value, which is cached on the client side:
    console.log(foo.myProperty);

    // Writing a property will instantly update the client side cache.
    // The remote end will be notified about the change asynchronously
    foo.myProperty = "Hello World!";

    // To get notified about remote property changes,
    // simply connect to the corresponding notify signal:
    foo.myPropertyChanged.connect(function() {
        console.log(foo.myProperty);
    });

    // One can also access enums that are marked with Q_ENUM:
    console.log(foo.MyEnum.MyEnumerator);
});

Überladene Methoden und Signale

Wenn Sie eine QObject veröffentlichen, die überladene Methoden hat, wird QWebChannel die Methodenaufrufe auf die beste Übereinstimmung auflösen. Beachten Sie, dass es aufgrund des JavaScript-Typensystems nur einen einzigen "number"-Typ gibt, der am besten auf einen C++-"double"-Typ abgebildet wird. Wenn sich Überladungen nur durch den Typ eines zahlenähnlichen Parameters unterscheiden, wählt QWebChannel immer die Überladung, die am besten zum JavaScript-Typ "number" passt. Wenn Sie eine Verbindung zu einem überladenen Signal herstellen, verbindet sich der QWebChannel Client standardmäßig nur mit der ersten Signalüberladung dieses Namens. Zusätzlich können Überladungen von Methoden und Signalen explizit durch ihre vollständige QMetaMethod Signatur angefordert werden. Angenommen, wir haben die folgende QObject Unterklasse auf der C++ Seite:

class Foo : public QObject
{
    Q_OBJECT
slots:
    void foo(int i);
    void foo(double d);
    void foo(const QString &str);
    void foo(const QString &str, int i);

signals:
    void bar(int i);
    void bar(const QString &str);
    void bar(const QString &str, int i);
};

Dann können Sie mit dieser Klasse auf der JavaScript-Seite wie folgt interagieren:

// methods
foo.foo(42); // will call the method named foo which best matches the JavaScript number parameter, i.e. foo(double d)
foo.foo("asdf"); // will call foo(const QString &str)
foo.foo("asdf", 42); // will call foo(const QString &str, int i)
foo["foo(int)"](42); // explicitly call foo(int i), *not* foo(double d)
foo["foo(QString)"]("asdf"); // explicitly call foo(const QString &str)
foo["foo(QString,int)"]("asdf", 42); // explicitly call foo(const QString &str, int i)

// signals
foo.bar.connect(...); // connect to first signal named bar, i.e. bar(int i)
foo["bar(int)"].connect(...); // connect explicitly to bar(int i)
foo["bar(QString)"].connect(...); // connect explicitly to bar(const QString &str)
foo["bar(QString,int)"].connect(...); // connect explicitly to bar(const QString &str, int i)

© 2025 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.