QT C++和HTML通信

摘要

在QT中和HTML进行通信通过websocket

转载请声明原创地址哟。

PS:对这块不熟有错误请指出

这换行有毒,谅解。 输入图片说明

概述: C++和HTML通过websocket通信,通过官方的qwebchannel.js实现。 C++和HTML共用一个对象并以此进行通信 C++通知HTML:通过信号 HTML通知C++:直接调用其函数 核心类:QWebChannel QT版本:5.6

首先:例子是使用QT自带的例子 大致组成: WebSocketClientWrapper:一个包装为了将WebSocketTransport作为信号参数让QWebChannel能接受到 WebSocketTransport:关键点之一,继承自QWebChannelAbstractTransport Dialog:用于通信的对象 index.html:演示用的html文件 qwebchannel.js:关键点之一,本人是搜索了整个QT找出来的有3个同名文件大小有些区别,具体内容没看过有哪些区别,看目录也就应该知道选哪个了,没有的话运行会报错的,功能:类似管理吧,即存储着注册对象的方法,信号之类的,当然要处理收到的信息后才能存下来。

代码分析: PS:C++是服务端,HTML是客户端 本人:先把其他的大致看一下然后从main出发 main.cpp

 
  1. #include "qwebchannel.h"

  2. #include <QApplication>

  3. #include <QDialog>

  4. #include <QVariantMap>

  5. #include <QDesktopServices>

  6. #include <QUrl>

  7. #include <QDir>

  8. #include <QFileInfo>

  9. #include <QtWebSockets/QWebSocketServer>

  10. #include "../shared/websocketclientwrapper.h"

  11. #include "../shared/websockettransport.h"

  12. #include "ui_dialog.h"

  13. class Dialog : public QObject

  14. {

  15. Q_OBJECT

  16. public:

  17. explicit Dialog(QObject *parent = 0)

  18. : QObject(parent)

  19. {

  20. ui.setupUi(&dialog);

  21. dialog.show();

  22. connect(ui.send, SIGNAL(clicked()), SLOT(clicked()));

  23. }

  24. void displayMessage(const QString &message)

  25. {

  26. ui.output->appendPlainText(message);

  27. }

  28. signals:

  29. void sendText(const QString &text);

  30. public slots:

  31. void receiveText(const QString &text)

  32. {

  33. displayMessage(tr("Received message: %1").arg(text));

  34. }

  35. private slots:

  36. void clicked()

  37. {

  38. const QString text = ui.input->text();

  39. if (text.isEmpty()) {

  40. return;

  41. }

  42. emit sendText(text);

  43. displayMessage(tr("Sent message: %1").arg(text));

  44. ui.input->clear();

  45. }

  46. private:

  47. QDialog dialog;

  48. Ui::Dialog ui;

  49. };

  50. int main(int argc, char** argv)

  51. {

  52. QApplication app(argc, argv);

  53. QFileInfo jsFileInfo(QDir::currentPath() + "/qwebchannel.js");

  54. if (!jsFileInfo.exists())

  55. QFile::copy(":/qtwebchannel/qwebchannel.js",jsFileInfo.absoluteFilePath());

  56. //这只是为了能把qwebchannel.js放到指定目录能让index.html找到,在我这然并卵.手动复制

  57. QWebSocketServer server(QStringLiteral("QWebChannel Standalone Example Server"), QWebSocketServer::NonSecureMode);

  58. //创建webSocket服务端,第二个参数应该是和关闭防火墙类似的操作,不进行安全检测

  59. if (!server.listen(QHostAddress::LocalHost, 12345)) {

  60. qFatal("Failed to open web socket server.");

  61. return 1;

  62. }

  63. //创建完后肯定要绑定啦,地址端口号要和HTML中的一样

  64. WebSocketClientWrapper clientWrapper(&server);

  65. /* 为了能将接受到的新连接的套接字包装成WebSocketTransport用信号传递给

  66. ** QWebChannel的void QWebChannel::connectTo(QWebChannelAbstractTransport *transport)

  67. ** 而接受参数正好是QWebChannelAbstractTransport,WebSocketTransport就是它的子类

  68. */

  69. QWebChannel channel;

  70. QObject::connect(&clientWrapper, &WebSocketClientWrapper::clientConnected,

  71. &channel, &QWebChannel::connectTo);

  72. /*

  73. ** 当有新连接即html端打开,serve将获得与之相连的新socket,接着触发WebSocketClientWrapper槽

  74. ** 将socket作为WebSocketTransport参数实例化这个对象,然后作为信号参数传递给QWebChannel

  75. ** QWebChannel就获得了与html通话的能力

  76. */

  77. Dialog dialog;

  78. channel.registerObject(QStringLiteral("dialog"), &dialog);//注册后能在HTML中使用

  79. //感觉就是这了,将Dialog的信号,函数等信息发给qwebchannel让其处理

  80. QUrl url = QUrl::fromLocalFile(BUILD_DIR "/index.html");

  81. QDesktopServices::openUrl(url);

  82. //这两句只是自动打开html而已,可以手动打开的哟

  83. //为了照顾下面那一行代码才没有将其删除

  84. dialog.displayMessage(QObject::tr("Initialization complete, opening browser at %1.").arg(url.toDisplayString()));

  85. return app.exec();

  86. }

  87. #include "main.moc"

  88. /*

  89. * 一般情况下,你的类会单独写,一个 ***.h, 一个 ***.cpp 。 类的定义在 头文件中,qmake可以调用moc自动处理(生成moc_***.h)并自动包含。

  90. 但你要是偷懒,比如把main函数和类的定义及实现都放到一个文件内,比如取名 main.cpp ,这时就不那么走运了,moc处理后生成 同名 的 .moc 文件,但这时你必须自己包含它了。

  91. */

服务端小结: 1.准备serve,绑定地址端口 2.收到链接后交给QWebChannel 3.准备对象用于被注册(感觉随便啦,有信号,有方法就行)PS:应该是C++和HTML共用一个实例 只是C++是直接调用,HTML是通过QWebChannel调用

服务端暂时这样了,接下来看看客户端吧 index.html

 
  1. <!DOCTYPE html>

  2. <html>

  3. <head>

  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

  5. <script type="text/javascript" src="./qwebchannel.js"></script>

  6. <script type="text/javascript">

  7. //BEGIN SETUP

  8. function output(message)

  9. {

  10. var output = document.getElementById("output");

  11. output.innerHTML = output.innerHTML + message + "\n";

  12. }

  13. //为了在打印信息而准备的方法

  14. window.onload = function() {

  15. if (location.search != "")

  16. var baseUrl = (/[?&]webChannelBaseUrl=([A-Za-z0-9\-:/\.]+)/.exec(location.search)[1]);

  17. else

  18. var baseUrl = "ws://localhost:12345";

  19. output("Connecting to WebSocket server at " + baseUrl + ".");

  20. var socket = new WebSocket(baseUrl);//创建一个Socket实例,连接到服务器

  21. //几个事件的绑定

  22. socket.onclose = function()

  23. {

  24. console.error("web channel closed");

  25. };

  26. socket.onerror = function(error)

  27. {

  28. console.error("web channel error: " + error);

  29. };

  30. socket.onopen = function()// 连接成功后触发

  31. {

  32. output("WebSocket connected, setting up QWebChannel.");

  33. //将socket交给qwebchannel.js,处理完后回调

  34. new QWebChannel(socket, function(channel) {

  35. // make dialog object accessible globally

  36. window.dialog = channel.objects.dialog;

  37. //应该是设置全局对象吧,objects里应该就存放着注册的对象

  38. document.getElementById("send").onclick = function() {

  39. var input = document.getElementById("input");

  40. var text = input.value;

  41. if (!text) {

  42. return;

  43. }

  44. output("Sent message: " + text);

  45. input.value = "";

  46. dialog.receiveText(text);

  47. }

  48. //HTML的send按钮的点击事件处理

  49. dialog.sendText.connect(function(message) {

  50. output("Received message: " + message);

  51. });

  52. //C++调用sendText时会使用到这里的匿名函数

  53. dialog.receiveText("Client connected, ready to send/receive messages!");

  54. //HTML直接调用函数

  55. output("Connected to WebChannel, ready to send/receive messages!");

  56. });

  57. }

  58. }

  59. //END SETUP

  60. </script>

  61. <style type="text/css">

  62. html {

  63. height: 100%;

  64. width: 100%;

  65. }

  66. #input {

  67. width: 400px;

  68. margin: 0 10px 0 0;

  69. }

  70. #send {

  71. width: 90px;

  72. margin: 0;

  73. }

  74. #output {

  75. width: 500px;

  76. height: 300px;

  77. }

  78. </style>

  79. </head>

  80. <body>

  81. <textarea id="output"></textarea><br />

  82. <input id="input" /><input type="submit" id="send" value="Send" onclick="javascript:click();" />

  83. </body>

  84. </html>

客户端小结: 1.链接到服务器,并写好对应事件的绑定 2.new QWebChannel 3.qwebchannel.js会帮我们处理的

最后注意: 这些也是得有的在WebSocketTransport中

输入图片说明 不要随便删。JSON也是要的传输的是JSON格式的数据

JS方面的能力比较渣,有错请喷,想深入了解的话可以去看源码,能力不足看晕了,不过这个qwebchannel.js倒是可以看一下,才400来行。 还是不太熟悉直接在参数里写函数,总觉得别扭,怪怪的。

FROM:https://my.oschina.net/LiangJYue/blog/668427

猜你喜欢

转载自blog.csdn.net/xiaomucgwlmx/article/details/88050317