Qt WebChannel JavaScript API
設(shè)置 JavaScript API
要與QWebChannel或WebChannel通信,客戶端必須使用并設(shè)置由qwebchannel.js. 對(duì)于在Qt WebEngine中運(yùn)行的客戶端,您可以通過qrc:///qtwebchannel/qwebchannel.js. 對(duì)于外部客戶端,您需要將文件復(fù)制到您的 Web 服務(wù)器。然后實(shí)例化一個(gè)QWebChannel對(duì)象并傳遞給它一個(gè)傳輸對(duì)象和一個(gè)回調(diào)函數(shù),一旦通道的初始化完成并且發(fā)布的對(duì)象變得可用,它們就會(huì)被調(diào)用。
傳輸對(duì)象實(shí)現(xiàn)了一個(gè)最小的消息傳遞接口。它應(yīng)該是一個(gè)帶有send()函數(shù)的對(duì)象,它接受一個(gè)字符串化的 JSON 消息并將其傳輸?shù)椒?wù)器端QWebChannelAbstractTransport對(duì)象。此外,onmessage當(dāng)收到來自服務(wù)器的消息時(shí),應(yīng)該調(diào)用它的屬性?;蛘?,您可以使用WebSocket來實(shí)現(xiàn)接口。
請(qǐng)注意,一旦傳輸對(duì)象完全可操作,就應(yīng)該構(gòu)造JavaScript QWebChannel對(duì)象。對(duì)于 WebSocket,這意味著您應(yīng)該在套接字的處理程序中創(chuàng)建QWebChannelonopen。查看Qt WebChannel Standalone Example以了解這是如何完成的。
與 QObject 交互
一旦調(diào)用了傳遞給QWebChannel對(duì)象的回調(diào),通道就完成了初始化,HTML 客戶端可以通過該channel.objects屬性訪問所有發(fā)布的對(duì)象。因此,假設(shè)一個(gè)對(duì)象是使用標(biāo)識(shí)符“foo”發(fā)布的,那么我們可以與它進(jìn)行交互,如下例所示。請(qǐng)注意,HTML 客戶端和 QML/C++ 服務(wù)器之間的所有通信都是異步的。屬性緩存在 HTML 端。此外請(qǐng)記住,只有可以轉(zhuǎn)換為 JSON 的 QML/C++ 數(shù)據(jù)類型才能正確(反)序列化,從而可供 HTML 客戶端訪問。
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.onMyPropertyChanged.connect(function(newValue) {
console.log(newValue);
});
// One can also access enums that are marked with Q_ENUM:
console.log(foo.MyEnum.MyEnumerator);
});
重載的方法和信號(hào)
當(dāng)您發(fā)布QObject具有重載方法的方法時(shí),QWebChannel會(huì)將方法調(diào)用解析為最佳匹配。請(qǐng)注意,由于 JavaScript 的類型系統(tǒng),只有一個(gè)“數(shù)字”類型最適合映射到 C++“double”。當(dāng)重載僅在類數(shù)字參數(shù)的類型上有所不同時(shí),QWebChannel將始終選擇最匹配 JavaScript 'number' 類型的重載。當(dāng)您連接到重載信號(hào)時(shí),QWebChannel客戶端默認(rèn)情況下將僅連接到該名稱的第一個(gè)重載信號(hào)。此外,方法和信號(hào)的重載可以通過它們的完整QMetaMethod簽名明確地請(qǐng)求。QObject假設(shè)我們?cè)?C++ 端有以下子類:
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);
};
然后你可以像這樣在 JavaScript 端與這個(gè)類進(jìn)行交互:
// 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)