Qt+ArcGIS Engine 10.1 开发(一)
?
?
Qt作為一個跨平臺C++圖形用戶界面應(yīng)用程序開發(fā)框架,相當(dāng)于微軟的MFC(只能運行在Windows平臺上),Qt命運多舛,幾經(jīng)易主,現(xiàn)在屬于芬蘭IT服務(wù)公司Digia。
Qt環(huán)境安裝
Qt的最新版本是Qt5.0,該版本是在12月中旬發(fā)布的,在這里我用的是Qt4.8。1版本,也不建議大家著急著用最新版本,關(guān)于軟件的下載地址可以在下面找到。
http://download.qt.nokia.com/qt/source/
http://qt-project.org/downloads#qt-other
安裝過程很單,只需要點擊下一部即可。
因為我采用的是VS2010作為Qt的集成開發(fā)環(huán)境,整個開發(fā)環(huán)境需要下載兩個軟件
http://download.qt.nokia.com/qt/source/qt-win-opensource-4.8.1-vs2010.exe
http://releases.qt-project.org/vsaddin/qt-vs-addin-1.1.11-opensource.exe
?
說明:
如果有人不愿意這么做,還可以使用QtCreator以及qt-win-opensource-4.8.1-mingw.exe的組合,因為新版本的QtCreator已經(jīng)不包含mingw,所以要單獨下載。
?
Qt的第一個程序
安裝完后,需要配置幾個環(huán)境變量,QMAKESPE(根據(jù)自己的情況配置,因為我用的是VS2010,所有配置win32-msvc2010),如下圖:
QTDIR(Qt的安裝目錄),如下圖:
在Path中添加Qt的bin目錄如下圖:
打開VS2010,新建工程可以找到Qt4 的模板:
?
?
完成之后,在VS中運行,出現(xiàn)下面的界面,因為我們什么都沒做,在彈出的界面上什么都沒有,不過沒關(guān)系,只要能出現(xiàn),就說明我們的Qt已經(jīng)可以使用了,如下圖:
?
ArcGIS Engine的環(huán)境
安裝ArcGIS ArcObjects for Cross Platform C++ 的SDK,這個沒有什么好說的。
ArcGIS Engine+Qt(控制臺開發(fā))
安裝了SDK之后,我們就需要將ArcGIS Engine的類庫等引入到開發(fā)環(huán)境中,在Qt中引入ArcGIS Engine的類庫等信息.在新建立的Qt控制臺程序工程右鍵,找到C/C++,然后找到常規(guī),在右側(cè)的附加包含目錄中輸入下面三個目錄的地址(因為我的有x(86),所以出現(xiàn)了下面的特殊符號):
說明:在MFC中我們除了引入三個目錄地址,還配置了預(yù)處理器定義"ESRI_WINDOW",在這里我并沒有配置。
配置好這個之后,在主程序文件中輸入代碼(這個代碼我在這里就不做解釋,到時候可以看這個文檔的姊妹篇- 《VC2010+ArcGIS Engine10.1開發(fā)》
,最后效果如下:
?
#include <QtCore/QCoreApplication>
#include "ArcSDK.h"
#include "qtextstream.h"
?
int main(int argc, char *argv[])
{
?
????::CoInitialize(NULL);
#pragma region 綁定許可
????IArcGISVersionPtr ipVer(__uuidof(VersionManager));
????VARIANT_BOOL succeeded;
????if (FAILED(ipVer->LoadVersion(esriArcGISEngine , L"10.1",&succeeded)))
????????return 0;
#pragma endregion
????//
#pragma region 初始化許可
????IAoInitializePtr ipInit(CLSID_AoInitialize);
????esriLicenseStatus status;
????ipInit->Initialize(esriLicenseProductCodeEngine, &status);
????if (status != esriLicenseCheckedOut)
????{
????????AoExit(0);
????????return 0;
????}
????????
#pragma endregion
?
????QCoreApplication a(argc, argv);
?
#pragma region 打開工作空間
????IWorkspaceFactoryPtr ipWorkspaceFactory(CLSID_ShapefileWorkspaceFactory);
????IWorkspacePtr pWs;
?
?
????BSTR bstr_str;
????QString q_str="D:\\guest\\chinasimplify";
????????bstr_str = SysAllocString(q_str.utf16());
?
????HRESULT hr=ipWorkspaceFactory->OpenFromFile(bstr_str,0,&pWs);
????SysFreeString(bstr_str);
????QString q_str1="china_simply.shp";
????????BSTR bStringWS=SysAllocString(q_str1.utf16());
?
????if (FAILED(hr))
????{
????????return 0;
????}
?
#pragma endregion
#pragma region QI 這里和NET下不一樣
????IFeatureWorkspacePtr ipRastWork (pWs);
?
#pragma endregion
?
#pragma region 打開要素類并獲取個數(shù)
????IFeatureClassPtr pFtClass;
?
????hr=ipRastWork->OpenFeatureClass(bStringWS,&pFtClass);
????SysFreeString(bStringWS);
?
????if (FAILED(hr))
????{
????????return 0;
????}
????long pCount=0;
????pFtClass->FeatureCount(NULL,&pCount);
#pragma endregion
?
???? QString s = QString::number(pCount, 10);
?
???? QTextStream cout(stdout);
?
???? cout<<s<< endl;
?
???? QString str;
???? QTextStream in(stdin);
???? in >> str;
?
????return a.exec();
}
?
運行后可以看到下面的效果
?
ArcGIS Engine+Qt(GUI開發(fā))
在MFC中我們介紹了兩種開發(fā)GUI的方法,一種是通過生成相應(yīng)的Activex控件MFC類,另一種是通過插入Activex控件的方法,在Qt里面做GUI的AE開發(fā),也有兩種不同的做法,而這兩種做法需要引入的頭文件也有差異,除了頭文件的差異,我們需要配置額外的信息,在這里我們分別對兩種方法介紹。
ArcGIS Engine+Qt(GUI開發(fā),使用Esri提供的控件類)
額外的配置
對于這種方法,需要配置很多信息,在工程項目的連接器的常規(guī)中找到SDK的lib目錄(在MFC的開發(fā)中,我們應(yīng)該沒有這個步驟),如下圖:
?
在附加依賴項中輸入qt4ctl.lib和aoctl.lib文件如下圖:
?
此外還要在環(huán)境變量中配置Path(不一定要在Path中配置,只要在運行的時候能找到相應(yīng)的文件即可),要不然在運行的時候會報下面的錯誤,如下圖:
?
這是因為Qt的AE在運行的時候用到了Engine安裝目錄下的bin下的三個文件:Qt4ctl.dll, aoctl.dll, ctlbase.dll,只要將Engine的bin目錄配置到Path中就可以了,如下圖:
Esri提供的控件類
當(dāng)這些信息配置好了,我們就可以開發(fā)出GUI程序了,在Qt中我們認(rèn)為一個可視化的組件是一個QWidget,這個QWidget類似MFC中的窗體,一旦有了這些QWidget,就可以用父組件的addWdiget方法加入,Esri提供了繼承這些控件QWidget的類,我們可以在qtaxtcl.h頭文件中找到,如下:
class ESRI_EXT_CLASS QAxCtl
????: public QWidget
{
public:
????QAxCtl(const char *progID = NULL, QWidget *parent = NULL, const char *name = NULL);
????QAxCtl(const ControlDataPtr progID, QWidget *parent = NULL, const char *name = NULL);
????~QAxCtl();
????HRESULT getInterface(IUnknown **ppUnk);
????HRESULT setCursor(HCURSOR cur);
protected:
????bool eventFilter(QObject *qo, QEvent *qe);
#if defined(ESRI_UNIX)
????bool x11Event(XEvent *event);
#endif /* ESRI_UNIX */
private:
????char *m_sProgID;
????AxContainerPtr m_pAxCont;
????void initialize(const char *progID);
};
代碼編寫
我們將這種GUI開發(fā)的先決條件都準(zhǔn)備好了,下來就開始一個簡單的GUI,這個例子我只將TOC,Map和Toolbar三個控件添加上去,并在Toolbar上添加了幾個命令和工具,完整的代碼如下(功能也比較簡單,界面也不好看,只是當(dāng)做一個例子,大家就將就看):
#include <stdio.h>
#include <qapplication.h>
#include <qpushbutton.h>
#include <qboxlayout.h>
#include <qsplitter.h>
?
#include <ArcSDK.h>
#include <AxCtl/qt4axctl.h>
#include <Ao/AoControls.h>
?
void add_toolbar_items(IToolbarControl* pToolbar);
?
int main(int argc, char **argv)
{
????????::CoInitialize(NULL);
#pragma region 綁定許可
????IArcGISVersionPtr ipVer(__uuidof(VersionManager));
????VARIANT_BOOL succeeded;
????if (FAILED(ipVer->LoadVersion(esriArcGISEngine , L"10.1",&succeeded)))
????????return 0;
#pragma endregion
?
????????IAoInitializePtr ipInit(CLSID_AoInitialize);
????????esriLicenseStatus status;
????????ipInit->Initialize(esriLicenseProductCodeEngine, &status);
????????if (status != esriLicenseCheckedOut)
????????{
????????????printf("Invalid Licensing.\n");
????????????AoExit(0);
????????}
????
????QApplication qapp(argc, argv);
?
????QWidget window;
?
????window.resize(500,400);
???? ?
????
????QVBoxLayout vbox(NULL);
?
????QAxCtl tlb(AoPROGID_ToolbarControl);
????tlb.setMinimumHeight(30);
????tlb.setMaximumHeight(30);
?
????QSplitter split;
????QAxCtl toc(AoPROGID_TOCControl);
????QAxCtl map(AoPROGID_MapControl);
????window.setLayout(&vbox);
?
????vbox.addWidget(&tlb);
split.addWidget(&toc);
?
????split.addWidget(&map);
?
????vbox.addWidget(&split);
????
????????IToolbarControlPtr ipToolbar;
????????IMapControl3Ptr ipMap;
????????ITOCControlPtr ipToc;
????????HRESULT hr;
?
????????hr = tlb.getInterface((IUnknown **)&ipToolbar);
????????hr = toc.getInterface((IUnknown **)&ipToc);
????????hr = map.getInterface((IUnknown **)&ipMap);
?
????????if (ipToolbar != 0)
????????????ipToolbar->SetBuddyControl(ipMap);
????????if (ipToc != 0)
????????????ipToc->SetBuddyControl(ipMap);
?
????????add_toolbar_items(ipToolbar);
?
????window.show();
????qapp.exec();????
????ipInit->Shutdown();
????::CoUninitialize();
????AoExit(0);
????return 0;
?
?
}
?
void add_toolbar_items(IToolbarControl* pToolbar)
{
????CComVariant varTool;
????long itemindex;
?
????if (!pToolbar)
????????return;
?
????varTool = L"esriControlCommands.ControlsOpenDocCommand";
????pToolbar->AddItem(varTool, 0, -1, VARIANT_FALSE, 0,
????????esriCommandStyleIconOnly, &itemindex);
????varTool = L"esriControlCommands.ControlsAddDataCommand";
????pToolbar->AddItem(varTool, 0, -1, VARIANT_FALSE, 0,
????????esriCommandStyleIconOnly, &itemindex);
?
????varTool = L"esriControlCommands.ControlsMapZoomInTool";
????pToolbar->AddItem(varTool, 0, -1, VARIANT_TRUE, 0,
????????esriCommandStyleIconOnly, &itemindex);
???? ?
????
????varTool = L"esriControlCommands.ControlsMapZoomOutTool";
????pToolbar->AddItem(varTool, 0, -1, VARIANT_FALSE, 0,
????????esriCommandStyleIconOnly, &itemindex);
????varTool = L"esriControlCommands.ControlsMapZoomInFixedCommand";
????pToolbar->AddItem(varTool, 0, -1, VARIANT_FALSE, 0,
????????esriCommandStyleIconOnly, &itemindex);
????varTool = L"esriControlCommands.ControlsMapZoomOutFixedCommand";
????pToolbar->AddItem(varTool, 0, -1, VARIANT_FALSE, 0,
????????esriCommandStyleIconOnly, &itemindex);
????varTool = L"esriControlCommands.ControlsMapPanTool";
????pToolbar->AddItem(varTool, 0, -1, VARIANT_FALSE, 0,
????????esriCommandStyleIconOnly, &itemindex);
????varTool = L"esriControlCommands.ControlsMapFullExtentCommand";
????pToolbar->AddItem(varTool, 0, -1, VARIANT_FALSE, 0,
????????esriCommandStyleIconOnly, &itemindex);
????varTool = L"esriControlCommands.ControlsMapZoomToLastExtentBackCommand";
????pToolbar->AddItem(varTool, 0, -1, VARIANT_FALSE, 0,
????????esriCommandStyleIconOnly, &itemindex);
????varTool = L"esriControlCommands.ControlsMapZoomToLastExtentForwardCommand";
????pToolbar->AddItem(varTool, 0, -1, VARIANT_FALSE, 0,
????????esriCommandStyleIconOnly, &itemindex);
????varTool = L"esriControlCommands.ControlsSelectFeaturesTool";
????pToolbar->AddItem(varTool, 0, -1, VARIANT_FALSE, 0,
????????esriCommandStyleIconOnly, &itemindex);
????varTool = L"esriControlCommands.ControlsSelectTool";
????pToolbar->AddItem(varTool, 0, -1, VARIANT_FALSE, 0,
????????esriCommandStyleIconOnly, &itemindex);
}
?
?
運行效果如下圖:
小結(jié)
這種方式跟在MFC中使用Axtivex的MFC類比較類似,都是自己實例化一個控件,然后將這個控件添加到父類控件中,但是Esri提供的這個方式,也有自己的弊端,不能調(diào)試,只能在Release版本下運行,估計是這中方式需要的幾個dll,沒有提供Debug版本的,如果調(diào)試,那么程序會在我們實例化控件的地方跳出去,這個問題搞了我好幾天,總找不到什么原因,借助偉大的Google,最后在Esri的英文論壇中也看到類似的,論壇中在求這個dll和相關(guān)lib的debug,看到這個,我也就明白了。
轉(zhuǎn)載于:https://www.cnblogs.com/zuiyirenjian/archive/2013/01/04/2843682.html
總結(jié)
以上是生活随笔為你收集整理的Qt+ArcGIS Engine 10.1 开发(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 获取GridView中RowComman
- 下一篇: c# xmlhttp POST提取远程w