天天看點

Qt編寫地圖綜合應用8-地圖互動

一、前言

最常用的地圖互動就幾個,比如滑鼠在地圖上按下的時候可以拾取經緯度坐标,然後傳給Qt程式,再比如對設定的裝置點進行單擊的時候,通知Qt程式單擊了哪一個裝置點,好讓Qt程式識别并作出反應比如彈出對應點的詳細資訊或者視訊預覽等。讓網頁執行js函數這種單向的操作,其實無論何種浏覽器核心都支援的,并不需要注入類或者添加qwebchannel.js檔案之類的,你隻需要放心大膽的調用runJavaScript或者evaluateJavaScript函數。而如果想要網頁發送對應的資料給Qt程式的話,就需要額外的處理了。

在webkit中要實作從網頁傳回資料互動,隻需要在網頁載入完畢的信号loadFinished中注入類對象即可 webView->page()->mainFrame()->addToJavaScriptWindowObject("objName", webJsData);,而在webengine控件中需要增加兩步,第一步是需要在網頁裡面引入js檔案 ,第二步是生成QWebChannel通信對象 new QWebChannel(qt.webChannelTransport, function(channel){window.receiveData = channel.objects.receiveData;}),第三步是注入類對象 QWebChannel *channel = new QWebChannel(this);channel->registerObject("objName", webJsData); webView->page()->setWebChannel(channel);

做完了上面的注入類以後,在網頁中寫好對應的window.receiveData即可,receiveData為對應的類的public的槽函數,這裡為了複用所有的資料傳回的情況,特意寫了通用的receiveData函數,void receiveData(const QString &type, const QVariant &data);定義兩個參數,這樣就涵蓋了所有的情況 type表示類型相當于唯一辨別,而data是QVariant類型,即可以是字元串也可以是整數或者數組,都能自動轉換的,這樣的話就一個類涵蓋了所有的各種可能的情況,都可以通過type來區分,通過data的類型去判斷并轉換資料。

二、功能特點

  1. 同時支援線上地圖和離線地圖兩種模式。
  2. 同時支援webkit核心、webengine核心、IE核心。
  3. 支援設定多個标注點,資訊包括名稱、位址、經緯度。
  4. 可設定地圖是否可單擊、拖動、滑鼠滾輪縮放。
  5. 可設定協定版本、秘鑰、主題樣式、中心坐标、中心城市、地理編碼位置等。
  6. 可設定地圖縮放比例和級别,縮略圖、比例尺、路況資訊等控件的可見。
  7. 支援地圖互動,比如滑鼠按下擷取對應位置的經緯度。
  8. 支援查詢路線,可設定起點位置、終點位置、路線模式、路線方式、路線方案(最少時間、最少換乘、最少步行、不乘地鐵、最短距離、避開高速)。
  9. 可顯示點線面工具,可直接在地圖上劃線、點、矩形、圓形等。
  10. 可設定行政區劃,指定某個城市區域繪制圖層,線上地圖自動輸出行政區劃邊界點集合到js檔案給離線地圖使用。
  11. 可靜态或者動态添加多個覆寫物。支援點、折線、多邊形、矩形、圓形、弧線、點聚合等。
  12. 函數接口友好和統一,使用簡單友善,就一個類。
  13. 支援js動态互動添加點、删除點、清空點、重置點,不需要重新整理頁面。
  14. 支援任意Qt版本、任意系統、任意編譯器。

三、體驗位址

  1. 國内站點: https://gitee.com/feiyangqingyun
  2. 國際站點: https://github.com/feiyangqingyun
  3. 個人首頁: https://blog.csdn.net/feiyangqingyun
  4. 知乎首頁: https://www.zhihu.com/people/feiyangqingyun/

四、效果圖

Qt編寫地圖綜合應用8-地圖互動

五、相關代碼

//需要自定義繼承自QObject的類來接收QWebEngineView互動資料,不然會列印很多煩人的資訊
class WebJsData : public QObject
{
    Q_OBJECT
public:
    static WebJsData *Instance();
    explicit WebJsData(QObject *parent = 0);

public slots:
    //定義兩個參數,這樣就涵蓋了所有的情況 type表示類型相當于唯一辨別
    void receiveData(const QString &type, const QVariant &data);

signals:
    void receiveDataFromJs(const QString &type, const QVariant &data);
};

WebJsData *WebJsData::Instance()
{
    static WebJsData self;
    return &self;
}

WebJsData::WebJsData(QObject *parent)
{
}

void WebJsData::receiveData(const QString &type, const QVariant &data)
{
    //可以在這裡重新梳理好再發出去信号
    emit receiveDataFromJs(type, data);
}

list << QString("  map.addEventListener(\"click\", function(e) {");
list << QString("    window.%1('point', e.point.lng + \",\" + e.point.lat);").arg(callFun);
list << QString("  });");

//自定義方法顯示标注詳細資訊
list << QString("  function addInfoWindow(marker, poi){");
list << QString("    var title = '<div style=\"color:#CE5521;\">' + poi.name + '</div>';");
list << QString("    var list = [];");
list << QString("    list.push('<table><tr style=\"vertical-align:top;line-height:25px;font-size:12px;\">');");
list << QString("    list.push('<td style=\"white-space:nowrap;word-break:keep-all;\">位址:</td>');");
list << QString("    list.push('<td>' + poi.addr + '</td>');");
list << QString("    list.push('</tr></table>');");
list << QString("    var infoWindow = new BMap.InfoWindow(list.join(\"\"),{title:title, width:60});");

//單擊以後彈出提示資訊或者發送信号出去
list << QString("    var markerClick = function() {");
#if 0
list << QString("      marker.openInfoWindow(infoWindow);");
#else
list << QString("      window.%1('marker', poi.name);").arg(callFun);
#endif
list << QString("    };");

//添加單擊監聽器
list << QString("    marker.addEventListener(\"click\", markerClick);");
list << QString("  }");           

繼續閱讀