QT:用QWebSocket實現webchannel,實現C++與HTML通訊
基本原理是通過channel將C++物件暴露給HTML,在HTML中呼叫qwebchannel.js。前提是建立transport,QT只提供了一個抽象基類QWebChannelAbstractTransport,需要自己進行實現,官方建議用QWebSocket實現,並給出了例項。
1、實現Transport類,內建一個WebSocket套接字;
2、實現新的channel類,內建一個WebSocketServer;
3、利用新的channel註冊C++物件,從而HTML可以使用該物件;
4、通過以下三種方式進行C++與HTML的互動:
4.1 在HTML中l連線C++ signal與js函式的
object.signal.connect(function(){});
4.2 在HTML中呼叫C++ public slots函式;
4.3 在HTML中呼叫C++ Q_INVOKABLE修飾的函式;
下面給出例項程式碼
5.1 WebSocketTransport類
websockettransport.h
1 #ifndef WEBSOCKETTRANSPORT_H 2 #define WEBSOCKETTRANSPORT_H 3 4 #include <QWebChannelAbstractTransport> 5 6 QT_BEGIN_NAMESPACE 7 class QWebSocket; 8 QT_END_NAMESPACE 9 10 class WebSocketTransport : public QWebChannelAbstractTransport 11 { 12 Q_OBJECT 13 public: 14 explicit WebSocketTransport(QWebSocket *socket); 15 virtual ~WebSocketTransport(); 16 17 void sendMessage(const QJsonObject &message) override; 18 19 private slots: 20 void textMessageReceived(const QString &message); 21 22 private: 23 QWebSocket *m_socket; 24 }; 25 26 #endif // WEBSOCKETTRANSPORT_H
websockettransport.cpp
1 #include "websockettransport.h" 2 3 #include <QDebug> 4 #include <QJsonDocument> 5 #include <QJsonObject> 6 #include <QWebSocket> 7 8 9 /*! 10 Construct the transport object and wrap the given socket. 11 12 The socket is also set as the parent of the transport object. 13 */ 14 WebSocketTransport::WebSocketTransport(QWebSocket *socket) 15 : QWebChannelAbstractTransport(socket) 16 , m_socket(socket) 17 { 18 connect(socket, &QWebSocket::textMessageReceived, 19 this, &WebSocketTransport::textMessageReceived); 20 connect(socket, &QWebSocket::disconnected, 21 this, &WebSocketTransport::deleteLater); 22 } 23 24 /*! 25 Destroys the WebSocketTransport. 26 */ 27 WebSocketTransport::~WebSocketTransport() 28 { 29 m_socket->deleteLater(); 30 } 31 32 /*! 33 Serialize the JSON message and send it as a text message via the WebSocket to the client. 34 */ 35 void WebSocketTransport::sendMessage(const QJsonObject &message) 36 { 37 QJsonDocument doc(message); 38 m_socket->sendTextMessage(QString::fromUtf8(doc.toJson(QJsonDocument::Compact))); 39 } 40 41 /*! 42 Deserialize the stringified JSON messageData and emit messageReceived. 43 */ 44 void WebSocketTransport::textMessageReceived(const QString &messageData) 45 { 46 QJsonParseError error; 47 QJsonDocument message = QJsonDocument::fromJson(messageData.toUtf8(), &error); 48 if (error.error) { 49 qWarning() << "Failed to parse text message as JSON object:" << messageData 50 << "Error is:" << error.errorString(); 51 return; 52 } else if (!message.isObject()) { 53 qWarning() << "Received JSON message that is not an object: " << messageData; 54 return; 55 } 56 emit messageReceived(message.object(), this); 57 }
5.2 WebSocketChannel類
websocketchannel.h
#ifndef WEBSOCKETCHANNEL_H #define WEBSOCKETCHANNEL_H #include <QWebChannel> class QWebSocketServer; class WebSocketTransport; //繼承QWebchannel類,在內部建立socket server與transport中socket的連線 class WebSocketChannel : public QWebChannel { Q_OBJECT public: WebSocketChannel(QWebSocketServer *server); signals: void clientConnected(WebSocketTransport *client); private slots: void handleNewConnection(); private: QWebSocketServer *_server; }; #endif // WEBSOCKETCHANNEL_H
websocketchannel.cpp
#include "websocketchannel.h" #include <QWebSocketServer> #include "websockettransport.h" WebSocketChannel::WebSocketChannel(QWebSocketServer *server) :_server(server) { connect(server, &QWebSocketServer::newConnection, this, &WebSocketChannel::handleNewConnection); connect(this, &WebSocketChannel::clientConnected, this, &WebSocketChannel::connectTo);//connectTo槽繼承自QWebchannel } void WebSocketChannel::handleNewConnection() { emit clientConnected(new WebSocketTransport(_server->nextPendingConnection())); }
main.cpp
#include <QApplication> #include <QDesktopServices> #include <QDialog> #include <QDir> #include <QFileInfo> #include <QUrl> #include <QWebChannel> #include <QWebSocketServer> int main(int argc, char** argv) { QApplication app(argc, argv); //建立QWebSocketServer,url是ws://localhost:12345 QWebSocketServer server(QStringLiteral("QWebChannel Standalone Example Server"), QWebSocketServer::NonSecureMode); if (!server.listen(QHostAddress::LocalHost, 12345)) { qFatal("Failed to open web socket server."); return 1; } //建立websocketchannl,該channel就可以用來通訊了 WebSocketChannel channel(&server); // setup the UI Dialog dialog; // setup the core and publish it to the QWebChannel Core core(&dialog); //註冊C++物件,該類要繼承自QObject channel.registerObject(QStringLiteral("core"), &core); // open a browser window with the client HTML page QUrl url = QUrl::fromLocalFile(BUILD_DIR "/index.html"); QDesktopServices::openUrl(url); dialog.displayMessage(Dialog::tr("Initialization complete, opening browser at %1.").arg(url.toDisplayString())); dialog.show(); return app.exec(); }
index.html
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> //使用qwebchannel.js <script type="text/javascript" src="./qwebchannel.js"></script> <script type="text/javascript"> //BEGIN SETUP function output(message) { var output = document.getElementById("output"); output.innerHTML = output.innerHTML + message + "\n"; } window.onload = function() { var baseUrl = "ws://localhost:12345"; output("Connecting to WebSocket server at " + baseUrl + "."); var socket = new WebSocket(baseUrl); socket.onclose = function() { console.error("web channel closed"); }; socket.onerror = function(error) { console.error("web channel error: " + error); }; socket.onopen = function() { output("WebSocket connected, setting up QWebChannel."); new QWebChannel(socket, function(channel) { // make core object accessible globally window.core = channel.objects.core; document.getElementById("send").onclick = function() { var input = document.getElementById("input"); var text = input.value; if (!text) { return; } output("Sent message: " + text); input.value = ""; //呼叫C++公有槽函式 core.receiveText(text); core.hello(text); } //連線C++訊號與javascript函式 core.sendText.connect(function(message) { output("Received message: " + message); }); core.receiveText("Client connected, ready to send/receive messages!"); output("Connected to WebChannel, ready to send/receive messages!"); }); } } //END SETUP </script> <style type="text/css"> html { height: 100%; width: 100%; } #input { width: 400px; margin: 0 10px 0 0; } #send { width: 90px; margin: 0; } #output { width: 500px; height: 300px; } </style> </head> <body> <textarea id="output"></textarea><br /> <input id="input" /><input type="submit" id="send" value="Send" onclick="javascript:click();" /> </body> </html>
相關文章
- C++ Qt開發:QUdpSocket實現組播通訊C++QTUDP
- HTTPS通訊的C++實現HTTPC++
- QT使用 http 協議通訊的實現示例QTHTTP協議
- 通訊錄管理系統(C++實現)C++
- 基於OpenSSL的HTTPS通訊C++實現HTTPC++
- (譯)通過WebChannel/WebSockets與QML中的HTML互動WebHTML
- C/C++ Qt Tree與Tab元件實現分頁選單C++QT元件
- 用Qt(C++)實現如蘋果般的亮屏效果QTC++蘋果
- C++ Qt開發:Tab與Tree元件實現分頁選單C++QT元件
- C/C++ Qt TabWidget 實現多窗體建立C++QT
- 通訊協議protobuf的原理與實現協議
- java實現UDP通訊JavaUDP
- 匿名管道通訊實現
- Qt實現系統托盤訊息QT
- 網路通訊2:TCP通訊實現TCP
- C/C++ Qt 資料庫與Chart實現歷史資料展示C++QT資料庫
- C++ Qt開發:TabWidget實現多窗體功能C++QT
- Qt Android 實現全屏QTAndroid
- QT實現ping功能QT
- 使用Java實現WebSocket通訊JavaWeb
- angular + express 實現websocket通訊AngularExpressWeb
- golang實現子程式通訊Golang
- Java實現TCP通訊程式JavaTCP
- Qt 使用第三方modbus-c庫實現Modbus通訊QT
- 用c++實現淨現值的計算C++
- Uniapp 使用 GoEasy 實現 websocket 實時通訊APPGoWeb
- provide 和 inject 實現祖先與後代的通訊IDE
- 通過 App Groups 實現程式間通訊APP
- Android Spingboot 實現SSE通訊案例Androidboot
- Go語言實現TCP通訊GoTCP
- WebRTC + WebSocket 實現視訊通話Web
- C# NModbus RTU通訊實現C#
- C語言實現TCP通訊C語言TCP
- WebSocket實現前後端通訊Web後端
- sharedWorker 實現多頁面通訊
- JAVA通訊(三)——實現多人聊天Java
- 如何優雅的實現訊息通訊?
- 在Spring Boot中實現WebSocket實時通訊Spring BootWeb