您的位置:首页 > 编程语言 > C语言/C++

QT:用QWebSocket实现webchannel,实现C++与HTML通信

2017-10-26 14:44 513 查看
http://www.cnblogs.com/wkcagd/p/7732330.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>


 
 
结果如下:


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  qt
相关文章推荐