首頁 > 軟體

Qt編寫地圖之實現跨平臺功能

2022-02-15 13:02:41

一、前言

跨平臺著實花了不少的精力,為了從Qt4.7相容到Qt6.2及後續版本,頭髮掉了不少,僅有的幾根毛所剩無幾,哎,可能這就是程式設計師的命,本人寫Qt程式這麼多年,比較喜歡支援多個Qt版本,尤其是鍾情於支援任意Qt版本+任意系統+任意編譯器,這句話說起來簡單其實實現起來就不容易了,首先你得有個很多版本的測試環境,起碼十幾個Qt環境要的吧,四五種作業系統要的吧,還要安裝各種VS版本免不了的,畢竟win上除了預設的mingw編譯器還有很多人用的是msvc編譯器,這麼一大堆環境折騰下來,沒有個1T硬碟是不夠的,而且官網釋出Qt版本的速度相當快,最慢半年肯定來一個版本,又得測試了,每次釋出一個大的版本,除了常用的windows以外,linux要測試吧,而且現在還多出來一些國產linux系統比如deepin new start UOS之類的,也要試試吧,哎呀好累。

二、功能特點

1 省市區域地圖封裝類功能特點

  1. 同時支援閃爍點圖、遷徙圖、區域地圖、世界地圖、儀表盤等。
  2. 可以設定標題、提示資訊、背景顏色、文字顏色、線條顏色、區域顏色等各種顏色。
  3. 可設定城市的名稱、值、經緯度 集合。
  4. 可設定地圖的放大倍數、是否允許滑鼠滾輪縮放。
  5. 內建世界地圖、全國地圖、省份地圖、地區地圖,可以精確到縣,所有地圖全部離線使用。
  6. 內建了各省市json資料檔案轉js檔案功能,如有資料更新自行轉換即可,支援單個檔案轉換和一鍵轉換所有檔案。
  7. 內建了從json檔案或者js檔案獲取該區域的所有名稱和經緯度資訊集合的功能,可以通過該方法獲取到資訊用來顯示。
  8. 依賴瀏覽器元件顯示地圖,提供的demo支援webkit/webengine/miniblink/ie 多種方式載入網頁。
  9. 採用miniblink瀏覽器核心打通了Qt5.6及後續版本+mingw編譯器缺少瀏覽器模組的遺憾,使得整個專案支援所有Qt版本,親測4.7到6.2等任意版本。
  10. 閃爍點遷徙圖等設定的點支援單獨設定顏色。
  11. 提供介面直接獲取點選的點相關資訊,方便程式聯動處理。
  12. 拓展性極強,可以依葫蘆畫瓢自行增加各種精美的echarts元件,做出牛逼的效果。
  13. 內建的儀表盤元件提供互動功能,demo演示中包含了對應的程式碼。
  14. 函數介面友好和統一,使用簡單方便,就一個類。
  15. 支援任意Qt版本、任意系統、任意編譯器。

2 百度地圖封裝類功能特點

  1. 同時支援線上地圖和離線地圖兩種模式。
  2. 同時支援webkit核心、webengine核心、miniblink核心、IE核心。
  3. 支援設定多個標註點,資訊包括名稱、地址、經緯度。
  4. 可設定地圖是否可單擊、拖動、滑鼠滾輪縮放。
  5. 可設定協定版本、祕鑰、主題樣式、中心座標、中心城市、地理編碼位置等。
  6. 可設定地圖縮放比例和級別,縮圖、比例尺、路況資訊等控制元件的可見。
  7. 支援地圖互動,比如滑鼠按下獲取對應位置的經緯度。
  8. 支援查詢路線,可設定起點位置、終點位置、路線模式、路線方式、路線方案(最少時間、最少換乘、最少步行、不乘地鐵、最短距離、避開高速)。
  9. 可顯示點線面工具,可直接在地圖上劃線、點、矩形、圓形等。
  10. 可設定行政區劃,指定某個城市區域繪製圖層,線上地圖自動輸出行政區劃邊界點集合到js檔案給離線地圖使用。
  11. 可靜態或者動態新增多個覆蓋物。支援點、折線、多邊形、矩形、圓形、弧線、點聚合等。
  12. 提供函數介面處理經緯度解析成地址和地址解析成經緯度座標。
  13. 提供的demo直接可以單獨選點執行對應的處理比如路線查詢。
  14. 可以拿到路線查詢到的點座標資訊集合,比如用於機器人座標導航等。
  15. 封裝了豐富的函數比如刪除指定點和所有點,刪除指定覆蓋物和所有覆蓋物等。
  16. 標註點彈框資訊可以自定義內容,標準html格式。
  17. 標註點單擊事件可選 0-不處理 1-自己彈框 2-傳送訊號。
  18. 標註點可設定動畫效果 0-不處理 1-跳動 2-墜落
  19. 標註點可設定本地圖片檔案等。
  20. 函數介面友好和統一,使用簡單方便,就一個類。
  21. 支援js動態互動新增點、刪除點、清空點、重置點,不需要重新整理頁面。
  22. 支援任意Qt版本、任意系統、任意編譯器。

3 離線地圖下載類功能特點

  1. 多執行緒同步下載多級別瓦片地圖,不卡介面。
  2. 內建多個離線地圖下載請求地址,自動隨機選擇一個傳送請求。
  3. 下載地圖型別同時支援街道圖和衛星圖。
  4. 自動計算可視區域或者行政區域的下載瓦片數量。
  5. 下載的級別可以自定義範圍和選擇。
  6. 每個瓦片下載完成都傳送訊號通知,引數包括下載用時。
  7. 可設定下載最大超時時間,超過了則丟棄跳到下一個下載任務。
  8. 實時顯示下載進度,以及當前級別已經下載的瓦片數和總瓦片數。
  9. 下載過程中可以停止下載,下載完成自動統計總用時。
  10. 內建經緯度和螢幕座標互相轉換函數。
  11. 目前支援百度地圖,其他地圖比如谷歌地圖、騰訊地圖、高德地圖可以客製化。
  12. 函數介面友好和統一,使用簡單方便,就一個類。
  13. 支援任意Qt版本、任意系統、任意編譯器。

4 省市輪廓下載類功能特點

  1. 定時器排隊下載省市輪廓圖點座標集合儲存到JS檔案。
  2. 支援一個行政區域多個不規則區域下載。
  3. 自動計算行政區域的下載輪廓數量。
  4. 可精確選擇省份、市區、縣城,也可直接輸入行政區域的名稱。
  5. 可以設定下載間隔、隨時開始下載和停止下載。
  6. 提供編輯邊界功能,可以直接在地圖上編輯好不規則區域的點集合,然後獲取邊界點集合資料,這個可以用來自己繪製區域拿到資料,比如某個鄉鎮甚至某個小區的行政區域資料,很牛逼。

三、體驗地址

體驗地址:https://pan.baidu.com/s/15ZKAlptW-rDcNq8zlzdYLg  提取碼:uyes 檔名:bin_map.zip

國內站點:https://gitee.com/feiyangqingyun

國際站點:https://github.com/feiyangqingyun

四、效果圖

五、相關程式碼

#include "webview.h"
#include "qevent.h"
#include "qdatetime.h"
#include "qdebug.h"

#ifdef webkit
#include <QtWebKit>
#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0))
#include <QtWebKitWidgets>
#endif
#elif webengine
#include <QtWebEngineWidgets>
#elif webie
#include <QAxWidget>
#elif webminiblink
#include "miniblink.h"
#endif

#define TIMEMS qPrintable(QTime::currentTime().toString("HH:mm:ss zzz"))
WebView::WebView(QWidget *parent) : QObject(parent)
{
    //初始化web控制元件設定資訊
    WebView::initWebSetting();
    //初始化通用地圖資料
    WebHelper::initMapData();

    //資料互動類
    webJsData = new WebJsData(this);
    connect(webJsData, SIGNAL(receiveDataFromJs(QString, QVariant)),
            this, SIGNAL(receiveDataFromJs(QString, QVariant)));

#ifdef webkit
    webView = new QWebView(parent);
#elif webengine
    webView = new QWebEngineView(parent);
    //設定對應的通訊通道
    QWebChannel *channel = new QWebChannel(this);
    channel->registerObject("objName", webJsData);
    webView->page()->setWebChannel(channel);
#elif webie
    webView = new QAxWidget(parent);
    //註冊瀏覽器控制元件
    webView->setControl("{8856F961-340A-11D0-A96B-00C04FD705A2}");
    //不顯示警告資訊
    webView->setProperty("DisplayAlerts", false);
    //不顯示卷軸
    webView->setProperty("DisplayScrollBars", true);
#elif webminiblink
    webView = new miniblink(parent);
#endif

    //關聯載入完成訊號
#if (defined webkit) || (defined webengine)
    connect(webView->page(), SIGNAL(loadFinished(bool)), this, SLOT(loadFinished()));
    connect(webView->page(), SIGNAL(loadFinished(bool)), this, SIGNAL(loadFinished(bool)));
#elif webminiblink
    connect(webView, SIGNAL(loadFinished(bool)), this, SLOT(loadFinished()));
    connect(webView, SIGNAL(loadFinished(bool)), this, SIGNAL(loadFinished(bool)));
    connect(webView, SIGNAL(receiveDataFromJs(QString, QVariant)),
            this, SIGNAL(receiveDataFromJs(QString, QVariant)));
#endif

    //設定沒有右鍵選單
#if (defined webkit) || (defined webengine) || (defined webie) || (defined webminiblink)
    webView->setContextMenuPolicy(Qt::NoContextMenu);
#endif

    //安裝事件過濾器
#ifdef webminiblink
    webView->installEventFilter(this);
#endif
}

void WebView::initWebSetting()
{
    //全域性設定只需要設定一次就行
    static bool isInit = false;
    if (!isInit) {
        isInit = true;
        QString webcore = "other";
#ifdef webkit
        webcore = "webkit";
        QWebSettings *webSetting = QWebSettings::globalSettings();
        webSetting->setAttribute(QWebSettings::JavascriptEnabled, true);
        webSetting->setAttribute(QWebSettings::PluginsEnabled, true);
        webSetting->setAttribute(QWebSettings::JavascriptCanOpenWindows, true);
#elif webengine
        webcore = "webengine";
        QWebEngineSettings *webSetting = QWebEngineProfile::defaultProfile()->settings();
        webSetting->setAttribute(QWebEngineSettings::JavascriptEnabled, true);
        webSetting->setAttribute(QWebEngineSettings::PluginsEnabled, true);
        webSetting->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, true);
#elif webie
        webcore = "ie";
#elif webminiblink
        webcore = "miniblink";
#endif
        qDebug() << TIMEMS << QString("init webview ok, core: %1").arg(webcore);
    }
}

bool WebView::eventFilter(QObject *watched, QEvent *event)
{
    //測試發現miniblink核心(其他核心正常),網頁中的右鍵有訊息會傳給父類別
    if (event->type() == QEvent::MouseButtonPress) {
        return true;
    }
    return QObject::eventFilter(watched, event);
}

void WebView::setLayout(QLayout *layout)
{
    //把控制元件加入到佈局
#if (defined webkit) || (defined webengine) || (defined webie) || (defined webminiblink)
    layout->addWidget(webView);
#endif
}

void WebView::setVisible(bool visible)
{
#if (defined webkit) || (defined webengine) || (defined webie) || (defined webminiblink)
    webView->setVisible(visible);
#endif
}

void WebView::setBgColor(const QColor &color)
{
#if (defined webkit) || (defined webie)
    webView->setStyleSheet(QString("background:%1;").arg(color.name()));
#elif (defined webengine)
    webView->page()->setBackgroundColor(color);
#elif (defined webminiblink)
    webView->setBgColor(color);
#endif
}

void WebView::loadFinished()
{
#ifdef webkit
    webView->page()->mainFrame()->addToJavaScriptWindowObject("objName", webJsData);
#endif
}

void WebView::load(const QString &url, const QString &html, const QString &baseUrl)
{
    //如果存在網址則優先直接載入網址
    if (!url.isEmpty()) {
#if (defined webkit) || (defined webengine)
        webView->load(QUrl(url));
#elif webie
        webView->dynamicCall("Navigate(const QString&)", url);
#elif webminiblink
        webView->load(url);
#endif
    } else {
#if (defined webkit) || (defined webengine)
        webView->setHtml(html, QUrl(baseUrl));
#elif webminiblink
        webView->setHtml(html, baseUrl);
#endif
    }
}

void WebView::runJs(const QString &js)
{
    if (js.isEmpty()) {
        return;
    }
#ifdef webkit
    webView->page()->mainFrame()->evaluateJavaScript(js);
#elif webengine
    webView->page()->runJavaScript(js);
#elif webminiblink
    webView->runJs(js);
#endif
}

以上就是Qt編寫地圖之實現跨平臺功能的詳細內容,更多關於Qt地圖 跨平臺的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com