基于我个人的上一篇内容,通过调用高德API创建了地图,链接如下。“QT6 调用高德地图API创建地图(初学者级)”
本篇根据上一篇所实现的内容基础上,使用QT中的webchannel方法实现与HTML交互,在HTML中使用了Javascript代码实现。实现鼠标左键点击某个位置即可获得该地点的经纬度坐标,效果如下:
1.项目结构如下:
.pro文件和main.cpp文件除了在.pro文件中加入几个模块以外,没有其他改动,因此直接放入代码
240505.pro
QT += core gui webenginewidgets webenginecore webchannel greaterThan(QT_MAJOR_VERSION, 4): QT += widgets CONFIG += c++17 # You can make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ main.cpp \ maplistener.cpp \ widget.cpp HEADERS += \ maplistener.h \ widget.h FORMS += \ widget.ui # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target
复制
main.cpp
#include "widget.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); return a.exec(); }
复制
2.创建一个c++的类,用于实现QT和HTML中的通信。代码如下
maplistener.h
#ifndef MAPLISTENER_H #define MAPLISTENER_H #include<QDebug> #include <QObject> class MapListener : public QObject { Q_OBJECT public: explicit MapListener(QObject *parent = nullptr); signals: void positionUpdated(const QString &position); // 声明一个信号 public slots: void updatePosition(const QString &position) { // 在这里处理接收到的经纬度数据 qDebug() << "Received position:" << position; emit positionUpdated(position); // 发出信号 } }; #endif // MAPLISTENER_H
复制
maplistener.cpp
#include "maplistener.h" MapListener::MapListener(QObject *parent) : QObject{parent} {}
复制
3.编写widget函数
在头文件中,只需要进行一个槽的声明即可(槽需要有函数实现,而信号不用)。这里面声明的槽跟maplistener.h中声明的信号后面组成一对。
widget.h
#ifndef WIDGET_H #define WIDGET_H #include <QtWidgets> #include <QWebEngineView> #include <QWidget> QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACE class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = nullptr); ~Widget(); private: Ui::Widget *ui; private slots: void onPositionUpdated(const QString &position); // 声明一个槽来更新 QTextEdit }; #endif // WIDGET_H
复制
在对应的cpp文件中,首先头文件声明的槽函数实现一下,可以根据自己的需要更改。我这里是把经纬度分别分开,然后显示在不同的textedit控件中。
在connect中,按照正常逻辑是在maplistener中直接放置控件,例如QWebEngineView的某个对象即可,例如名为web_widget的QWebEngineView控件。但是由于是web端,所以没有办法直接通信,因此我们需要通过QT给我们的webchannel方法来实现。
在使用方法中,new一个QWebChannel对象,并且指向自己创建的窗口。
其中下方这两行代码是非常重要的,并且QStringLiteral("maplistener")这个“maplistener”名称就是对应的要连接的html中到时候要使用的javascript的名称,通过这个名称可以调用maplistener中的成员。
QWebChannel *channel = new QWebChannel(ui->web_widget->page()); channel->registerObject(QStringLiteral("maplistener"), maplistener);
复制
下面是在html中javascript调用的方法。
channel.objects.maplistener.updatePosition(lnglat);
复制
widget.cpp
#include "widget.h" #include "ui_widget.h" #include <QWebEngineView> #include <QWebChannel> #include <QObject> #include"maplistener.h" Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); ui->web_widget->setUrl(QUrl("http://localhost:8000/获取经纬度坐标(实验).html")); MapListener *maplistener = new MapListener(this); QWebChannel *channel = new QWebChannel(ui->web_widget->page()); channel->registerObject(QStringLiteral("maplistener"), maplistener); ui->web_widget->page()->setWebChannel(channel); connect(maplistener,&MapListener::positionUpdated,this,&Widget::onPositionUpdated); } Widget::~Widget() { delete ui; } void Widget::onPositionUpdated(const QString &position) { // 使用逗号作为分隔符来分割字符串 QStringList parts = position.split(","); // 检查是否至少有两个部分 if (parts.size() >= 2) { // 移除可能的空格或换行符,并转换为浮点数(如果需要的话) QString part1 = parts[0].trimmed(); QString part2 = parts[1].trimmed(); // 将分割后的部分设置到对应的QTextEdit中 ui->textEdit1->setText(part1); ui->textEdit2->setText(part2); } else { // 如果字符串没有按预期分割,可以设置一些默认值或显示错误信息 ui->textEdit1->setText("Invalid position (part 1)"); ui->textEdit2->setText("Invalid position (part 2)"); } }
复制
widget.h
#ifndef WIDGET_H #define WIDGET_H #include <QtWidgets> #include <QWebEngineView> #include <QWidget> QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACE class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = nullptr); ~Widget(); private: Ui::Widget *ui; private slots: void onPositionUpdated(const QString &position); // 声明一个槽来更新 QTextEdit }; #endif // WIDGET_H
复制
4.编写HTML文件以及其中的Javascript代码
在这个部分需要用到qwbchannel.js文件,这个文件直接从自己安装目录下面的“QT.6\Examples\Qt-6.5.3\webchannel\shared”这个文件夹下获得即可,记得这个js文件要跟html放在同一个位置,不然找不到好像。不是很懂,希望有大哥解答一下!
获取经纬度坐标(实验).html
<!doctype html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width"> <title>鼠标拾取地图坐标</title> <link rel="stylesheet" href="https://a.amap.com/jsapi_demos/static/demo-center/css/demo-center.css" /> <script type="text/javascript" src="https://cache.amap.com/lbs/static/addToolbar.js"></script> <script type="text/javascript" src="./src/qwebchannel.js"></script> </head> <style type="text/css"> html,body{ width: 100%; height: 100%; margin: 0px; } .map{ height: 100%; width: 100%; float: left; } </style> <body> <div id="container" class="map"></div> </div> <script src="https://webapi.amap.com/maps?v=1.4.15&key=“输入自己注册的key”&plugin=AMap.Autocomplete"></script> <script src="qwebchannel.js"></script> <script type="text/javascript"> new QWebChannel(qt.webChannelTransport, function (channel) { // 为地图注册click事件获取鼠标点击出的经纬度坐标 var map = new AMap.Map("container", { mapStyle: "amap://styles/blue",resizeEnable: true }); map.on('click', function(e) { var lnglat = e.lnglat.getLng() + ',' + e.lnglat.getLat(); // 假设你在 Qt 端注册了一个名为 'mapListener' 的对象,并且它有一个 'updatePosition' 方法 channel.objects.maplistener.updatePosition(lnglat); }); }); </script> </body> </html>
复制