<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>陈关州的博客</title>
  
  <subtitle>More Professional</subtitle>
  <link href="/atom.xml" rel="self"/>
  
  <link href="http://www.chenguanzhou.com/"/>
  <updated>2022-01-07T03:19:22.120Z</updated>
  <id>http://www.chenguanzhou.com/</id>
  
  <author>
    <name>陈关州</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Windows平台下各种Markdown编辑器功能对比</title>
    <link href="http://www.chenguanzhou.com/2016/02/16/markdowneditor/"/>
    <id>http://www.chenguanzhou.com/2016/02/16/markdowneditor/</id>
    <published>2016-02-16T03:40:05.000Z</published>
    <updated>2022-01-07T03:19:22.120Z</updated>
    
    <content type="html"><![CDATA[<p>不多说，上图：</p><a id="more"></a><p><img src="/images/markdown.png" alt="对比" title="Win平台下Markdown编辑器功能对比"></p><p><a href="/images/markdown.png">大图</a></p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;不多说，上图：&lt;/p&gt;
    
    </summary>
    
    
  </entry>
  
  <entry>
    <title>QGIS开发教程(3)——如何学习QGIS开发(通过PyQGIS文档)</title>
    <link href="http://www.chenguanzhou.com/2015/05/17/qgis-3-how-to-learn/"/>
    <id>http://www.chenguanzhou.com/2015/05/17/qgis-3-how-to-learn/</id>
    <published>2015-05-17T07:56:24.000Z</published>
    <updated>2022-01-07T03:19:22.136Z</updated>
    
    <content type="html"><![CDATA[<center><strong>（本文为本人原创，请尊重个人劳动成果。未经本人许可，严禁转载！）</strong></center><h1 id="自主学习QGIS开发"><a href="#自主学习QGIS开发" class="headerlink" title="自主学习QGIS开发"></a>自主学习QGIS开发</h1><p>虽然<code>QGIS</code>本身功能强大，但还是架不住我们要编写新的功能、新的业务流程、新的算法。前文中我们提到，扩展<code>QGIS</code>有2种方法，一是用<code>Python</code>、<code>C++</code>来写QGIS的插件；另一种就是基于<code>QGIS</code>的<code>C++ API</code>开发独立应用程序。然而后者资料甚少，官方<code>C++ API</code>文档也非常简略，我也不可能把所有功能都列举出来，放到博客里。因此我们想要开发更多功能，就得借助一大利器——<code>PyQGIS</code>的文档了。</p><a id="more"></a><h1 id="PyQGIS"><a href="#PyQGIS" class="headerlink" title="PyQGIS"></a>PyQGIS</h1><blockquote><p>Python是一种面向对象、直译式的电脑程式语言，具有近二十年的发展历史。它包含了一组功能完备的标准库，能够轻松完成很多常见的任务。它的语法简单，与其它大多数程式设计语言使用大括号不一样，它使用缩进来定义语句块。</p></blockquote><p><code>Python</code>由于有着较高的开发效率，并且具有胶水语言的特性，被广泛应用于各种系统当中。<code>ArcGIS</code>与<code>QGIS</code>也不例外。<code>QGIS</code>项目中，使用了<a href="https://wiki.python.org/moin/SIP" target="_blank" rel="noopener"><code>sip</code></a>库来实现<code>Python</code>与<code>C++</code>代码的绑定。<code>QGIS</code>官方称之为<code>PyQGIS</code>。</p><p><code>QGIS</code>软件里面，专门有一个<code>Python</code>的控制台，用于使用<code>Python</code>脚本，实现一些特殊功能。开启方法为：<code>Plugins → Python Console</code>。效果图如下：</p><p><img src="/images/QGIS/console.png" alt="Python Console" title="Python控制台"></p><p>由于<code>Python</code>的种种优势，<code>QGIS</code>官方写了一个<a href="http://docs.qgis.org/testing/en/docs/pyqgis_developer_cookbook/index.html" target="_blank" rel="noopener">PyQGIS cookbook</a>的文档，里面对<code>PyQGIS</code>进行了详细的介绍。文档内容包括但不限于：<br>-载入图层<br>-使用栅格图层<br>-使用矢量图层<br>-处理几何形体<br>-投影变换<br>-地图渲染、打印</p><p>研究<code>PyQGIS</code>文档，就会发现，里面各个类的名称，与<code>QGIS</code>的<code>C++ API</code>中的名称一样。因此，我们可以通过<code>QGIS</code>的<code>Python</code>文档，来学习QGIS C++的开发。</p><h1 id="举例——载入图层"><a href="#举例——载入图层" class="headerlink" title="举例——载入图层"></a>举例——载入图层</h1><p>上一篇中提到的，我们的第一个<code>QGIS</code>程序中的一个功能，就是打开<code>Shapefile</code>文件，并显示出来。如果我们通过<code>PyQGIS</code>的文档，该怎样学习开发呢？</p><p>我们应该先在<code>PyQGIS</code>中，找到相应功能的文档介绍。比如载入图层，就是：<a href="http://docs.qgis.org/testing/en/docs/pyqgis_developer_cookbook/loadlayer.html" target="_blank" rel="noopener">http://docs.qgis.org/testing/en/docs/pyqgis_developer_cookbook/loadlayer.html</a></p><p>里面介绍载入<code>OGR</code>图层（<code>Shapefile</code>属于<code>OGR</code>图层），代码如下：<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vlayer = QgsVectorLayer(<span class="string">"/path/to/shapefile/file.shp"</span>, <span class="string">"layer_name_you_like"</span>, <span class="string">"ogr"</span>)</span><br></pre></td></tr></table></figure></p><p>我们”翻译“成<code>C++</code>的代码，就是：<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">QgsVectorLayer *vlayer = <span class="keyword">new</span> QgsVectorLayer(<span class="string">"/path/to/shapefile/file.shp"</span>, <span class="string">"layer_name_you_like"</span>, <span class="string">"ogr"</span>);</span><br></pre></td></tr></table></figure></p><p>可以看出来，<code>Python</code>代码转化为<code>C++</code>代码非常方便。</p><p>文档中还介绍了载入栅格图层的<code>Python</code>代码：<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">fileName = <span class="string">"/path/to/raster/file.tif"</span></span><br><span class="line">fileInfo = QFileInfo(fileName)</span><br><span class="line">baseName = fileInfo.baseName()</span><br><span class="line">rlayer = QgsRasterLayer(fileName, baseName)</span><br><span class="line"><span class="keyword">if</span> <span class="keyword">not</span> rlayer.isValid():</span><br><span class="line">  <span class="keyword">print</span> <span class="string">"Layer failed to load!"</span></span><br></pre></td></tr></table></figure></p><p>其对应的<code>C++</code>代码就可以写成：<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">QString fileName = <span class="string">"/path/to/raster/file.tif"</span>;</span><br><span class="line">QString fileInfo = QFileInfo(fileName);</span><br><span class="line">QString baseName = fileInfo.baseName();</span><br><span class="line">QgsRasterLayer *rlayer = <span class="keyword">new</span> QgsRasterLayer(fileName, baseName);</span><br><span class="line"><span class="keyword">if</span> (!rlayer.isValid())</span><br><span class="line">  qDebug()&lt;&lt;<span class="string">"Layer failed to load!"</span>;</span><br></pre></td></tr></table></figure></p><h1 id="小结"><a href="#小结" class="headerlink" title="小结"></a>小结</h1><p>通过<code>PyQGIS</code>文档，我们可以了解<code>QGIS</code>的基本开发方法，也能很容易地将<code>Python</code>代码转化为<code>C++</code>代码。</p>]]></content>
    
    <summary type="html">
    
      &lt;center&gt;&lt;strong&gt;（本文为本人原创，请尊重个人劳动成果。未经本人许可，严禁转载！）&lt;/strong&gt;&lt;/center&gt;

&lt;h1 id=&quot;自主学习QGIS开发&quot;&gt;&lt;a href=&quot;#自主学习QGIS开发&quot; class=&quot;headerlink&quot; title=&quot;自主学习QGIS开发&quot;&gt;&lt;/a&gt;自主学习QGIS开发&lt;/h1&gt;&lt;p&gt;虽然&lt;code&gt;QGIS&lt;/code&gt;本身功能强大，但还是架不住我们要编写新的功能、新的业务流程、新的算法。前文中我们提到，扩展&lt;code&gt;QGIS&lt;/code&gt;有2种方法，一是用&lt;code&gt;Python&lt;/code&gt;、&lt;code&gt;C++&lt;/code&gt;来写QGIS的插件；另一种就是基于&lt;code&gt;QGIS&lt;/code&gt;的&lt;code&gt;C++ API&lt;/code&gt;开发独立应用程序。然而后者资料甚少，官方&lt;code&gt;C++ API&lt;/code&gt;文档也非常简略，我也不可能把所有功能都列举出来，放到博客里。因此我们想要开发更多功能，就得借助一大利器——&lt;code&gt;PyQGIS&lt;/code&gt;的文档了。&lt;/p&gt;
    
    </summary>
    
      <category term="QGIS开发教程" scheme="http://www.chenguanzhou.com/categories/QGIS%E5%BC%80%E5%8F%91%E6%95%99%E7%A8%8B/"/>
    
    
      <category term="Qt" scheme="http://www.chenguanzhou.com/tags/Qt/"/>
    
      <category term="QGIS" scheme="http://www.chenguanzhou.com/tags/QGIS/"/>
    
      <category term="C++" scheme="http://www.chenguanzhou.com/tags/C/"/>
    
      <category term="Shapefile" scheme="http://www.chenguanzhou.com/tags/Shapefile/"/>
    
      <category term="Python" scheme="http://www.chenguanzhou.com/tags/Python/"/>
    
      <category term="PyQGIS" scheme="http://www.chenguanzhou.com/tags/PyQGIS/"/>
    
  </entry>
  
  <entry>
    <title>QGIS开发教程(2)——第一个QGIS项目</title>
    <link href="http://www.chenguanzhou.com/2015/05/10/qgis-2-first/"/>
    <id>http://www.chenguanzhou.com/2015/05/10/qgis-2-first/</id>
    <published>2015-05-10T06:17:18.000Z</published>
    <updated>2022-01-07T03:19:22.120Z</updated>
    
    <content type="html"><![CDATA[<center><strong>（本文为本人原创，请尊重个人劳动成果。未经本人许可，严禁转载！）</strong></center><h1 id="新建Qt项目"><a href="#新建Qt项目" class="headerlink" title="新建Qt项目"></a>新建Qt项目</h1><p>按照如下格式，新建一个项目的pro文件（可以是<code>Qt Creator</code>创建，也可以是<code>qmake</code>来创建）：</p><a id="more"></a><pre><code>QT       += core gui xmlgreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsTARGET = 1_FirstAppTEMPLATE = appSOURCES += main.cpp\        mainwindow.cppHEADERS  += mainwindow.hLIBS += -lqgis_core -lqgis_guiunix{DEFINES += CORE_EXPORT=DEFINES += GUI_EXPORT=}!unix{DEFINES += CORE_EXPORT=__declspec(dllimport)DEFINES += GUI_EXPORT=__declspec(dllimport)}</code></pre><p>需要注意的是：</p><ol><li>使用<code>QGIS</code>时，必须要包含<code>Qt</code>的<code>XML</code>模块</li><li><code>LIBS += -lqgis_core  -lqgis_gui</code>表明，该程序要包含两个lib文件：qgis_core.lib、qgis_gui.lib(以Win中OSGeo4W为例，这俩文件在<code>C:\OSGeo4W64\apps\qgis\lib</code>)</li><li>使用<code>QGIS</code>需要定义两个宏（如果用别的模块还有有其他的宏需要定义），<code>Unix</code>系统下定义<code>CORE_EXPORT</code>、<code>GUI_EXPORT</code>为空即可，<code>Win</code>下需要定义为<code>__declspec(dllimport)</code>。</li></ol><p>在使用<code>QGIS</code>库时，项目还需要能够找到<code>QGIS</code>项目的头文件及lib文件所在路径。因此我们需要告诉项目<code>include</code>和<code>lib</code>所在的路径。许多人直接在pro文件里面显示指定路径，然而我并不推荐这样使用，因为这会破坏项目的跨平台性。（在<code>Linux</code>系统下，默认是不需要显式指定的）</p><p>我的做法是，设置两个环境变量，分别为<code>lib</code>与<code>include</code>，将所用第三方库头文件、库文件所在路径都加到变量里面去。另外，程序运行的时候还需要在Path变量里面找到dll所在路径。下面是我添加的环境变量（Windows OSGeo4W为例）：</p><pre><code>lib      C:\OSGeo4W64\apps\qgis\lib;C:\OSGeo4W64\libinclude  C:\OSGeo4W64\apps\qgis\include;C:\OSGeo4W64\includepath     C:\OSGeo4W64\bin;C:\OSGeo4W64\apps\qgis\bin</code></pre><h1 id="添加代码"><a href="#添加代码" class="headerlink" title="添加代码"></a>添加代码</h1><p>在<code>main.cpp</code>里面，把<code>QApplication</code>替换为<code>QgsApplication</code>，并且其构造函数要增加第三个参数。<br><code>main.cpp</code>代码如下：</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"mainwindow.h"</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;QDir&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;qgsapplication.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">char</span> *argv[])</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line"><span class="function">QgsApplication <span class="title">a</span><span class="params">(argc, argv, <span class="literal">true</span>)</span></span>;</span><br><span class="line">QgsApplication::setPluginPath(QDir::currentPath()+<span class="string">"/Plugins"</span>);</span><br><span class="line">QgsApplication::initQgis();</span><br><span class="line">MainWindow w;</span><br><span class="line">w.show();</span><br><span class="line"></span><br><span class="line"><span class="keyword">return</span> a.exec();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>其中，<code>QgsApplication::setPluginPath(QDir::currentPath()+&quot;/Plugins&quot;);</code>表示指定<code>QGIS</code>插件路径为程序所在目录下<code>Plugins</code>文件夹。因此在运行程序之前，需要将<code>QGIS</code>所有插件（<code>Win</code>下是dll文件）复制到这个文件夹下面来，否则程序无法读取空间数据。（<code>OSGeo4W</code>中，<code>QGIS</code>插件路径为<code>C:\OSGeo4W64\apps\qgis\plugins</code>）</p><p>现在，就可以直接运行程序，弹出一个空白的对话框：<br><img src="/images/QGIS/empty_window.jpg" alt="EmptyDialog" title="空白的窗体"></p><h1 id="打开Shapefile文件"><a href="#打开Shapefile文件" class="headerlink" title="打开Shapefile文件"></a>打开Shapefile文件</h1><p>现在我们来对<code>MainWindow</code>类进行操作，使其具有打开矢量文件并显示的功能。代码如下：</p><p>mainwindow.h</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">ifndef</span> MAINWINDOW_H</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> MAINWINDOW_H</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;QMainWindow&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">QgsMapCanvas</span>;</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MainWindow</span> :</span> <span class="keyword">public</span> QMainWindow</span><br><span class="line">&#123;</span><br><span class="line">Q_OBJECT</span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">MainWindow(QWidget *parent = <span class="number">0</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> slots:</span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">open</span><span class="params">()</span></span>;<span class="comment">//Open file</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">QgsMapCanvas *canvas;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span> <span class="comment">// MAINWINDOW_H</span></span></span><br></pre></td></tr></table></figure><p>mainwindow.cpp</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"mainwindow.h"</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;QtCore&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;QMenuBar&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;QFileDialog&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;QMessageBox&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;qgsmaplayerregistry.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;qgsmapcanvas.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;qgsvectorlayer.h&gt;</span></span></span><br><span class="line"></span><br><span class="line">MainWindow::MainWindow(QWidget *parent)</span><br><span class="line">: QMainWindow(parent),canvas(<span class="keyword">new</span> QgsMapCanvas(<span class="keyword">this</span>))</span><br><span class="line">&#123;</span><br><span class="line"><span class="keyword">this</span>-&gt;resize(<span class="number">800</span>,<span class="number">600</span>);</span><br><span class="line"></span><br><span class="line">QMenuBar *menuBar = <span class="keyword">new</span> QMenuBar(<span class="keyword">this</span>);</span><br><span class="line">menuBar-&gt;addAction(tr(<span class="string">"Open File"</span>),<span class="keyword">this</span>,SLOT(open()));</span><br><span class="line"><span class="keyword">this</span>-&gt;setMenuBar(menuBar);</span><br><span class="line"></span><br><span class="line"><span class="keyword">this</span>-&gt;setCentralWidget(canvas);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">void</span> MainWindow::open()</span><br><span class="line">&#123;</span><br><span class="line">QString path = QFileDialog::getOpenFileName(<span class="keyword">this</span>,tr(<span class="string">"Open File"</span>),QString(),<span class="string">"ESRI Shapefile(*.shp)"</span>);</span><br><span class="line"><span class="keyword">if</span> (path.isEmpty())  <span class="keyword">return</span>;</span><br><span class="line"></span><br><span class="line">QgsVectorLayer *layer = <span class="keyword">new</span> QgsVectorLayer(path,QFileInfo(path).completeBaseName(),<span class="string">"ogr"</span>);</span><br><span class="line"><span class="keyword">if</span> (!layer-&gt;isValid())</span><br><span class="line">&#123;</span><br><span class="line">QMessageBox::critical(<span class="keyword">this</span>,tr(<span class="string">"Error"</span>),tr(<span class="string">"Open file failed!\nReason:%1"</span>).arg(layer-&gt;lastError()));</span><br><span class="line"><span class="keyword">return</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">QgsMapLayerRegistry::instance()-&gt;addMapLayer(layer);</span><br><span class="line">canvas-&gt;setLayerSet(QList&lt;QgsMapCanvasLayer&gt;()&lt;&lt;QgsMapCanvasLayer(layer));</span><br><span class="line">canvas-&gt;zoomToFullExtent();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><code>QGIS</code>程序中，显示、渲染空间数据的Widget类是<code>QgsMapCanvas</code>类，该类的<code>setLayerSet()</code>函数用来控制canvas中待显示的图层。<code>QgsVectorLayer</code>的一个对象，就代表一个矢量图层。<br>需要注意的是，往画布里面添加新的图层时，要在<code>QgsMapLayerRegistry::instance()</code>对象中进行注册。</p><p>程序运行，并打开一个<code>Shapefile</code>文件的效果图如下（一定要记得将<code>QGIS</code>的<code>Plugins</code>目录复制到程序所在路径）：</p><p><img src="/images/QGIS/first_app.jpg" alt="FirstImage" title="效果图"></p><p>PS：使用OSGeo4W时，由于只提供了Release版的QGIS，因此也只能编译Release版的程序。如果程序需要调试，可以考虑采用log的方式。</p><h1 id="代码"><a href="#代码" class="headerlink" title="代码"></a>代码</h1><p>本教程所有例子的代码，托管在Github上，地址：<a href="https://github.com/chenguanzhou/QGIS-Cpp-API-Tutorial" target="_blank" rel="noopener">https://github.com/chenguanzhou/QGIS-Cpp-API-Tutorial</a></p>]]></content>
    
    <summary type="html">
    
      &lt;center&gt;&lt;strong&gt;（本文为本人原创，请尊重个人劳动成果。未经本人许可，严禁转载！）&lt;/strong&gt;&lt;/center&gt;

&lt;h1 id=&quot;新建Qt项目&quot;&gt;&lt;a href=&quot;#新建Qt项目&quot; class=&quot;headerlink&quot; title=&quot;新建Qt项目&quot;&gt;&lt;/a&gt;新建Qt项目&lt;/h1&gt;&lt;p&gt;按照如下格式，新建一个项目的pro文件（可以是&lt;code&gt;Qt Creator&lt;/code&gt;创建，也可以是&lt;code&gt;qmake&lt;/code&gt;来创建）：&lt;/p&gt;
    
    </summary>
    
      <category term="QGIS开发教程" scheme="http://www.chenguanzhou.com/categories/QGIS%E5%BC%80%E5%8F%91%E6%95%99%E7%A8%8B/"/>
    
    
      <category term="Qt" scheme="http://www.chenguanzhou.com/tags/Qt/"/>
    
      <category term="QGIS" scheme="http://www.chenguanzhou.com/tags/QGIS/"/>
    
      <category term="C++" scheme="http://www.chenguanzhou.com/tags/C/"/>
    
      <category term="Shapefile" scheme="http://www.chenguanzhou.com/tags/Shapefile/"/>
    
  </entry>
  
  <entry>
    <title>QGIS开发教程(1)——QGIS开发准备工作</title>
    <link href="http://www.chenguanzhou.com/2015/05/09/qgis-1-preparation/"/>
    <id>http://www.chenguanzhou.com/2015/05/09/qgis-1-preparation/</id>
    <published>2015-05-09T08:19:32.000Z</published>
    <updated>2022-01-07T03:19:22.120Z</updated>
    
    <content type="html"><![CDATA[<center><strong>（本文为本人原创，请尊重个人劳动成果。未经本人许可，严禁转载！）</strong></center><h1 id="获取编译好的QGIS"><a href="#获取编译好的QGIS" class="headerlink" title="获取编译好的QGIS"></a>获取编译好的QGIS</h1><p><code>QGIS</code>是跨平台的，因此在不同平台上获取编译好的<code>QGIS</code>方法也不尽相同。<br>我不推荐直接从源码编译<code>QGIS</code>（但是需要保留一份源代码以供学习），因为<code>QGIS</code>的依赖库实在是太多了，配置比较复杂。并且，QGIS更新频繁，不可能每次出来新的Release，都要再来编译一遍啊。</p><a id="more"></a><h2 id="1-Windows"><a href="#1-Windows" class="headerlink" title="1. Windows"></a>1. Windows</h2><p>在<code>Windows</code>系统上，可以通过<a href="http://trac.osgeo.org/osgeo4w/" target="_blank" rel="noopener"><code>OSGeo4W</code>项目</a> 来获取包括<code>QGIS</code>、<code>GDAL</code>在内的开源空间库的二进制开发包。如果电脑是64位的，推荐使用64位的<code>OSGeo4W</code>。在安装的过程中，要选中<code>&quot;Advanced Install&quot;</code>，然后要勾选<code>&quot;qgis-devel&quot;</code>。<br>安装完毕后，基于<code>VS2010</code>编译的<code>QGIS</code>就配置好了。</p><h2 id="2-Linux-amp-Mac-OS"><a href="#2-Linux-amp-Mac-OS" class="headerlink" title="2. Linux &amp; Mac OS"></a>2. Linux &amp; Mac OS</h2><p>在非<code>Windows</code>平台上安装<code>QGIS</code>，只需按照<a href="http://www.qgis.org/en/site/forusers/download.html" target="_blank" rel="noopener">官方说明</a> 操作即可。</p><h1 id="基础学习"><a href="#基础学习" class="headerlink" title="基础学习"></a>基础学习</h1><p><code>QGIS</code>源代码托管在<code>Github</code>上面，（<a href="https://github.com/qgis/QGIS" target="_blank" rel="noopener">我是传送门</a> ）。学习<code>QGIS</code>，少不了查阅源代码，因此我们有必要拖一份源代码到本机上来。</p><p>为了弄清楚QGIS源代码结构，我们有必要掌握以下工具的基本使用方法：</p><h2 id="1-Git-amp-amp-Github"><a href="#1-Git-amp-amp-Github" class="headerlink" title="1. Git &amp;&amp; Github"></a>1. Git &amp;&amp; Github</h2><p>Git是一个分布式版本控制系统，读者可以阅读<a href="http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/001373962845513aefd77a99f4145f0a2c7a7ca057e7570000" target="_blank" rel="noopener">《Git教程》</a> 来了解。<br>Github是一个代码托管网站，用户可以通过Git将代码托管在Github上面。目前，主流的开源项目都会将源代码托管在Github上。</p><h2 id="2-Qt"><a href="#2-Qt" class="headerlink" title="2. Qt"></a>2. Qt</h2><p><code>QGIS</code>是基于<code>Qt4</code>开发的（之前的博客介绍过Qt）。<code>Qt</code>目前最新版本是5.4，但是<code>QGIS</code>暂时只支持Qt4（<code>QGIS</code>最新版开始支持<code>Qt5</code>了，但需要自己编译）。</p><p>在<code>Windows</code>系统下面，使用<code>OSGeo4W</code>安装<code>QGIS</code>后，应该也就自动安装好了<code>Qt4</code>。</p><p><code>Qt</code>入门推荐看这个系列：<a href="http://www.devbean.net/2012/08/qt-study-road-2-catelog/" target="_blank" rel="noopener">《Qt 学习之路 2》</a></p><h2 id="3-Qt-Creator（qmake）"><a href="#3-Qt-Creator（qmake）" class="headerlink" title="3. Qt Creator（qmake）"></a>3. Qt Creator（qmake）</h2><p>本系列<code>QGIS</code>教程，使用<code>Qt Creator</code>作为IDE，因为使用<code>Qt Creator</code>来开发<code>Qt</code>项目是最爽的（并且是跨平台的）。<br><code>Qt Creator</code><a href="http://www.qt.io/download-open-source" target="_blank" rel="noopener">下载地址</a><br>一般在Qt Creator中的基于Qt的程序，大都由qmake构建，项目信息写在pro文件中（Qt Creator还支持CMake构建的项目）。</p><pre><code>qmake是一个协助简化跨平台进行项目开发的构建过程的工具程序，Qt附带的工具之一 。qmake能够自动生成Makefile、Microsoft Visual Studio 项目文件 和 xcode 项目文件。不管源代码是否是用Qt写的，都能使用qmake，因此qmake能用于很多软件的构建过程。</code></pre><p>by 维基百科——<a href="http://zh.wikipedia.org/zh-cn/Qmake" target="_blank" rel="noopener">qmake</a></p><h1 id="QGIS的代码结构"><a href="#QGIS的代码结构" class="headerlink" title="QGIS的代码结构"></a>QGIS的代码结构</h1><p>进入<code>QGIS</code>源代码文件夹，可以看见，其目录结构如下：</p><pre><code>QGIS├─.tx                        ├─cmake                 CMake相关文件├─cmake_templates├─debian                Debian系统相关配置文件├─doc                   文档├─i18n                  国际化文件（翻译）├─images                图表├─mac                   Mac OS系统相关配置文件├─ms-windows            Windows系统相关配置文件├─postinstall├─python                PyQGIS├─resources             资源文件├─scripts               脚本文件├─src                   C++源代码文件├─tests                 测试└─tools                    </code></pre><p>其中，我们只关心src文件夹：</p><pre><code>QGIS├─src│  ├─analysis            空间分析模块，对应qgis_analysis.dll│  ├─app                 主程序，对应qgis-bin.exe│  ├─astyle              Artistic Style│  ├─browser             QGIS的浏览器，对应qgis-browser-bin.exe│  ├─core                QGIS核心模块，对应qgis_core.dll│  ├─crssync        │  ├─customwidgets       QGIS在Qt Creator中的控件│  ├─designer            │  ├─gui                 QGIS的GUI界面模块，对应qgis_gui.dll│  ├─helpviewer          QGIS帮助浏览器│  ├─mapserver│  ├─plugins             QGIS插件│  ├─providers           QGIS数据Provider│  ├─python              QGIS内置Python解析器模块，对应qgispython.dll│  └─ui                  QGIS界面UI文件</code></pre><p>由其源码我们看到，<code>QGIS</code>由<code>CMake</code>管理构建，内部采用模块化开发。</p><h1 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h1><p>如果现在电脑上按照上述要求，有了完整的QGIS-开发包（Win下面就是lib、dll和一堆头文件）和Qt4、QtCreator，那么就可以开始进行基于QGIS的开发了！</p>]]></content>
    
    <summary type="html">
    
      &lt;center&gt;&lt;strong&gt;（本文为本人原创，请尊重个人劳动成果。未经本人许可，严禁转载！）&lt;/strong&gt;&lt;/center&gt;

&lt;h1 id=&quot;获取编译好的QGIS&quot;&gt;&lt;a href=&quot;#获取编译好的QGIS&quot; class=&quot;headerlink&quot; title=&quot;获取编译好的QGIS&quot;&gt;&lt;/a&gt;获取编译好的QGIS&lt;/h1&gt;&lt;p&gt;&lt;code&gt;QGIS&lt;/code&gt;是跨平台的，因此在不同平台上获取编译好的&lt;code&gt;QGIS&lt;/code&gt;方法也不尽相同。&lt;br&gt;我不推荐直接从源码编译&lt;code&gt;QGIS&lt;/code&gt;（但是需要保留一份源代码以供学习），因为&lt;code&gt;QGIS&lt;/code&gt;的依赖库实在是太多了，配置比较复杂。并且，QGIS更新频繁，不可能每次出来新的Release，都要再来编译一遍啊。&lt;/p&gt;
    
    </summary>
    
      <category term="QGIS开发教程" scheme="http://www.chenguanzhou.com/categories/QGIS%E5%BC%80%E5%8F%91%E6%95%99%E7%A8%8B/"/>
    
    
      <category term="Qt" scheme="http://www.chenguanzhou.com/tags/Qt/"/>
    
      <category term="QGIS" scheme="http://www.chenguanzhou.com/tags/QGIS/"/>
    
      <category term="C++" scheme="http://www.chenguanzhou.com/tags/C/"/>
    
      <category term="Git" scheme="http://www.chenguanzhou.com/tags/Git/"/>
    
  </entry>
  
  <entry>
    <title>QGIS开发教程(0)——GIS平台现状</title>
    <link href="http://www.chenguanzhou.com/2015/05/08/qgis-introduction/"/>
    <id>http://www.chenguanzhou.com/2015/05/08/qgis-introduction/</id>
    <published>2015-05-08T09:23:26.000Z</published>
    <updated>2022-01-07T03:19:22.136Z</updated>
    
    <content type="html"><![CDATA[<center><strong>（本文为本人原创，请尊重个人劳动成果。未经本人许可，严禁转载！）</strong></center><h1 id="引子"><a href="#引子" class="headerlink" title="引子"></a>引子</h1><p>在开发遥感影像处理系统，或者其他GIS系统的时候，开发者往往都会面临一个选择，就是是基于现有的商业/开源平台开发，还是自己重新从底层开始造轮子。</p><p>如果选择从0开始，就又会面临新的问题：</p><ul><li>怎样选择图形图像库（<code>GDI</code>、<code>GDI+</code>、<code>Direct2D</code>、<code>OpenGL</code>等）？</li><li>怎样解码栅格、矢量数据（<code>GeoTiff</code>、<code>IMG</code>、<code>Shapefile</code>等）？</li><li>怎样解决较大数据量（比如数据量比内存还大）的栅格与矢量文件的快速显示、渲染问题？</li><li>怎样解决坐标系与投影的问题？</li><li>……</li></ul><a id="more"></a><p>我本科闲的无聊的时候，写过一个基于<code>OpenGL</code>和<code>GDAL</code>的用来显示栅格影像的COM组件。但是只能显示单幅栅格影像，并且不支持矢量（真的很困难）。后来又写过一个基于<code>Direct2D</code>的<code>Shapefile</code>浏览器（只能简单显示轮廓）。所以我知道，对于开发者来说，从零开始开发并不是最优选择。基于现有平台/库来开发才是效率最高、性能最优的。</p><p>那么，现在新问题又来了，到底是选择那种平台呢？目前而言，比较成熟的商用GIS平台就是：</p><ul><li><code>ESRI ArcGIS</code></li></ul><p>可是它价格不菲，用来进行商业开发是非常不错的选择，如果只是想写写开原算法或者小系统，就显得过于庞大了（需要带一个AE Runtime。现在ESRI推出了基于移动端的ArcGIS Runtime，但由于对栅格数据支持有限，被排除在我们讨论范围了）。所以我们就把目光转向了开源社区，开源社区中最常见的GIS平台有以下两个：</p><ul><li><code>QGIS</code>（<code>C++</code> <code>Qt</code>）</li><li><code>SharpMap</code>（<code>C#</code> <code>Windows Form</code>）</li></ul><p>在实际中，<code>SharpMap</code>有着种种bug（对中文路径支持不佳、对WPF支持不佳等，栅格影像渲染速度慢等），所以我们暂时不详细讨论它。</p><h1 id="QGIS"><a href="#QGIS" class="headerlink" title="QGIS"></a>QGIS</h1><p><code>QGIS</code>是一个免费开源的地理信息系统，基于<code>Qt</code>库，有着完整的栅格矢量数据渲染、空间分析的能力，并且支持多种语言的插件式扩展（<code>C++</code>、<code>Python</code>），还完美支持Utf8字符串路径，简直完爆<code>SharpMap</code>啊。</p><p>目前，官方推荐的开发方式，就是在<code>QGIS</code>里面的<code>Python</code>控制台中，写<code>Python</code>代码。官方文档的<a href="http://docs.qgis.org/2.6/en/docs/pyqgis_developer_cookbook/" target="_blank" rel="noopener">传送门</a>。</p><p>当然我这个系列要讲的，是基于<code>QGIS C++ API</code>的独立应用程序开发（俗称“基于QGIS的二次开发”），这方面官方文档的<a href="http://qgis.org/api/2.6/" target="_blank" rel="noopener">传送门在这</a>。当然了，这个文档只有每个类的信息，并没有教大家怎么写基于<code>QGIS</code>的程序。</p><h1 id="这个系列的目的"><a href="#这个系列的目的" class="headerlink" title="这个系列的目的"></a>这个系列的目的</h1><p>因为<code>QGIS</code>官方没有告诉大家（或者说是不推荐），该如何写基于<code>QGIS</code>的独立应用程序；而国内写的《基于QGIS二次开发》还停留在<code>QGIS 1.x</code>版本里，并且还在使用VS开发。</p><p>所以经过这一年来的探索，我有必要将我学习、实践<code>QGIS</code>开发的经验分享给大家。</p><h1 id="所需基本技能"><a href="#所需基本技能" class="headerlink" title="所需基本技能"></a>所需基本技能</h1><p>要想系统地进行<code>QGIS</code>开发，必须要掌握（或者基本掌握）以下技能：</p><ul><li><code>C++</code></li><li><code>Qt</code></li><li>基本RS、GIS常识</li></ul><p>若能掌握以下技术更好：</p><ul><li><code>Git</code></li><li><code>CMake</code>、<code>qmake</code></li><li>跨平台开发经验</li><li>基本UI、UE</li><li>熟悉<code>Python</code>开发</li></ul><h1 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h1><p>重要的事情要说三遍：</p><ul><li><code>QGIS</code>的License是<code>GPL</code> </li><li><code>QGIS</code>的License是<code>GPL</code> </li><li><code>QGIS</code>的License是<code>GPL</code> </li></ul><p>这就说明，基于QGIS的程序，必须开源。希望大家能够支持知识产权。</p>]]></content>
    
    <summary type="html">
    
      &lt;center&gt;&lt;strong&gt;（本文为本人原创，请尊重个人劳动成果。未经本人许可，严禁转载！）&lt;/strong&gt;&lt;/center&gt;

&lt;h1 id=&quot;引子&quot;&gt;&lt;a href=&quot;#引子&quot; class=&quot;headerlink&quot; title=&quot;引子&quot;&gt;&lt;/a&gt;引子&lt;/h1&gt;&lt;p&gt;在开发遥感影像处理系统，或者其他GIS系统的时候，开发者往往都会面临一个选择，就是是基于现有的商业/开源平台开发，还是自己重新从底层开始造轮子。&lt;/p&gt;
&lt;p&gt;如果选择从0开始，就又会面临新的问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;怎样选择图形图像库（&lt;code&gt;GDI&lt;/code&gt;、&lt;code&gt;GDI+&lt;/code&gt;、&lt;code&gt;Direct2D&lt;/code&gt;、&lt;code&gt;OpenGL&lt;/code&gt;等）？&lt;/li&gt;
&lt;li&gt;怎样解码栅格、矢量数据（&lt;code&gt;GeoTiff&lt;/code&gt;、&lt;code&gt;IMG&lt;/code&gt;、&lt;code&gt;Shapefile&lt;/code&gt;等）？&lt;/li&gt;
&lt;li&gt;怎样解决较大数据量（比如数据量比内存还大）的栅格与矢量文件的快速显示、渲染问题？&lt;/li&gt;
&lt;li&gt;怎样解决坐标系与投影的问题？&lt;/li&gt;
&lt;li&gt;……&lt;/li&gt;
&lt;/ul&gt;
    
    </summary>
    
      <category term="QGIS开发教程" scheme="http://www.chenguanzhou.com/categories/QGIS%E5%BC%80%E5%8F%91%E6%95%99%E7%A8%8B/"/>
    
    
      <category term="Qt" scheme="http://www.chenguanzhou.com/tags/Qt/"/>
    
      <category term="QGIS" scheme="http://www.chenguanzhou.com/tags/QGIS/"/>
    
      <category term="C++" scheme="http://www.chenguanzhou.com/tags/C/"/>
    
      <category term="Python" scheme="http://www.chenguanzhou.com/tags/Python/"/>
    
      <category term="3S" scheme="http://www.chenguanzhou.com/tags/3S/"/>
    
  </entry>
  
  <entry>
    <title>Qt云服务/云计算平台QTC（Qt Cloud Services）入门（0）—— Introduction</title>
    <link href="http://www.chenguanzhou.com/2014/09/26/2014-09-26-QTC-Introduction/"/>
    <id>http://www.chenguanzhou.com/2014/09/26/2014-09-26-QTC-Introduction/</id>
    <published>2014-09-26T06:07:49.000Z</published>
    <updated>2022-01-07T03:19:22.120Z</updated>
    
    <content type="html"><![CDATA[<center><strong>（本文为本人原创，请尊重个人劳动成果。未经本人许可，严禁转载！）</strong></center><p>在这个“大数据”的时代，传统的跨平台C++库Qt已经将魔爪丧心病狂的伸向了“云计算”。在2012年的Qt开发者大会上，Qt发布了BaaS(Backend as a Service)服务——<code>Enginio</code>，旨在为用户提供一个NoSQL数据库的后端平台。截至到（2014年9月），<a href="http://qtcloudservices.com" target="_blank" rel="noopener">Qt云服务</a>(Qt Cloud Services，简称“QTC”)已经发展成为了提供以下三种服务的云平台：</p><ul><li><a href="https://developer.qtcloudservices.com/mar/introduction" target="_blank" rel="noopener">Managed Application Runtime (MAR)</a></li><li><a href="https://developer.qtcloudservices.com/eds/introduction" target="_blank" rel="noopener">Enginio Data Storage (EDS)</a></li><li><a href="https://developer.qtcloudservices.com/mws/introduction" target="_blank" rel="noopener">Managed WebSocket (MWS)</a></li></ul><a id="more"></a><p>鉴于这三种应用都有Qt SDK（Qt5.3以上）的支持，又由于Qt跨平台的特性（支持Mac, Win, Win8, Linux, Android, IOS, WP等平台），使得我们开发云应用变得更加简单。用户想要更大的带宽或存储空间、更多的读写次数，只要给钱，QTC就能无缝扩展。</p><p>“1GB的免费空间，2万5千次读写次数”可以看出，在价格方面Qt对免费用户还是挺厚道的。具体的价格政策详见<a href="https://qtcloudservices.com/pricing/" target="_blank" rel="noopener">QTC官网信息</a>。</p><p>QTC非常详细的文档源于Qt优良的传统。想要详细学习QTC的各种技术，可以直接访问<a href="https://developer.qtcloudservices.com/qtc" target="_blank" rel="noopener">官方文档</a>。然而，QTC还处于起步阶段，只有设在欧洲的服务器，致使国内访问网速较慢，甚至存在被墙的风险。并且不排除今后QTC在国内设服务器，或者直接被墙的可能，所以不排除以后QTC在国内架设服务器的可能。</p><p>本次QTC入门系列，我打算MAR/EDS/MWS都至少写一篇介绍。由于我没有学过计算机网络，也不对网络编程了解也不多，因次文章中如有错误或漏洞，烦请指出。</p><p>由于QTC文档里面写着：</p><blockquote><p>This is a Beta release of the Managed Application Runtime. As a result, the API is subject to change. Developers should take this into consideration when using this release.</p></blockquote><p>和</p><blockquote><p>This is a Beta release of the Managed WebSocket. As a result, the API is subject to change. Developers should take this into consideration when using the Beta release of the Managed WebSocket.</p></blockquote><p>所以本系列文章里面所提到的具体的API有可能会失效，请大家谅解。</p><p>下面就简要介绍这三种应用：</p><hr><h1 id="1-Managed-Application-Runtime-MAR"><a href="#1-Managed-Application-Runtime-MAR" class="headerlink" title="1. Managed Application Runtime (MAR)"></a>1. Managed Application Runtime (MAR)</h1><p>MAR从字面可以看出，是一个托管的应用运行时，可以将源代码通过Git的方式上传到QTC的服务器中，在线部署编译，属于PaaS(Platform-as-a-Service)。从官方给出的examples可以看出，MAR支持以下服务器端的语言：</p><ul><li><a href="https://github.com/qtcloudservices/mar-sample-qt" target="_blank" rel="noopener">Qt/C++</a></li><li><a href="https://github.com/qtcloudservices/mar-sample-node" target="_blank" rel="noopener">Node.Js</a></li><li><a href="https://github.com/qtcloudservices/mar-sample-ruby" target="_blank" rel="noopener">Ruby</a></li></ul><p>也就是说，我们可以很方便的把本地编写的程序，稍微改造一下，部署到服务器端。MAR因为用到了Git，所以要求用户会使用Git的基本操作。</p><p>PS：从QTC的价格信息来看，免费用户只能创建“单核256M内存”的虚拟机，但是我现在能够创建“4核1024M内存”的机器。</p><h1 id="2-Enginio-Data-Storage-EDS"><a href="#2-Enginio-Data-Storage-EDS" class="headerlink" title="2. Enginio Data Storage (EDS)"></a>2. Enginio Data Storage (EDS)</h1><p>EDS就是之前所说的Qt提供的最早的云服务——Enginio。它提供了一个<a href="http://zh.wikipedia.org/zh-cn/NoSQL" target="_blank" rel="noopener">NoSQL</a>数据库（NoSQL这几年很火呀），用来存储非关系型数据(non-relational data)。EDS可以通过<code>REST APIs</code>来访问，也可以通过Qt的Enginio SDK(C++/QML)来访问，当然也支持直接在网页上管理数据库。</p><p>在EDS平台中，我们可以管理数据，也能管理数据的权限、进行账户认证(Authentication)、存储文件、进行全文搜索等。</p><p>在Qt5.3的SDK中，就包含了Enginio模块。并且官方也给出了三个C++示例：Cloud Address Book、Image Gallery和Todos；同时也给了4个基于QML的例子：Image Gallery、Social Todos、Todos、Users。每个例子都能在Qt的SDK或者文档中找到。Enginio的SDK，不仅提供了EnginioClient类，用来处理数据的传送，还封装了EnginioModel类，利用Qt的Model/View模型来简化云端与本地的数据交互。</p><h1 id="3-Managed-WebSocket-MWS"><a href="#3-Managed-WebSocket-MWS" class="headerlink" title="3. Managed WebSocket (MWS)"></a>3. Managed WebSocket (MWS)</h1><p>由于我不熟悉WebSocket，只好借助<a href="http://zh.wikipedia.org/zh-cn/WebSocket" target="_blank" rel="noopener">Wiki</a>了：</p><blockquote><p>WebSocket是HTML5开始提供的一种浏览器与服务器间进行全双工通讯的网络技术。 WebSocket通信协议于2011年被IETF定为标准 RFC 6455，WebSocketAPI被W3C定为标准。</p><p>在WebSocket API中，浏览器和服务器只需要做一个握手的动作，然后，浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。</p></blockquote><p>WebSocket被称为“Web的TCP”，通过WebSocket可以简化实时Web应用的开发。具体应用可以参照IBM的这篇文章：<a href="http://www.ibm.com/developerworks/cn/web/1112_huangxa_websocket/index.html" target="_blank" rel="noopener">《使用 HTML5 WebSocket 构建实时 Web 应用》</a>。</p><p>MWS就是托管在QTC上的WebSocket，MWS客户端和服务器端的SDK已经包含在Qt5.3里面了，同时社区提供的Android/Node.js/Ruby的SDK也挂在了官方文档里。官网官方示例是一个<a href="https://github.com/qtcloudservices/qtc-qtexamples-chat" target="_blank" rel="noopener">聊天室</a>程序。</p><hr><p>#首次使用QTC要注意的事情<br>由于“云计算”涉及到众多技术，因次在QTC上部署运行应用之前，要注意以下事项：</p><ul><li>要<a href="http://qtcloudservices.com" target="_blank" rel="noopener">申请</a>一个Qt/QTC的账号（可以利用Github账号登陆）</li><li>了解Git。至少得知道常用的Push/Pull/Commit/Branch操作。能够<a href="https://developer.qtcloudservices.com/mar/key-concepts/personal-ssh-keys" target="_blank" rel="noopener">生成</a>SSL密钥</li><li>安装了Qt5.3以上版本，并且熟悉Qt的SDK(C++或QML)，了解“网络”的基本概念。不熟悉的话，就要闷声<a href="http://www.w3school.com.cn/index.html" target="_blank" rel="noopener">学习一个</a></li><li>要经常看Qt和QTC的文档，并且要看得懂（4级水平）</li><li>要有探索未知的欲望……</li><li>要经常看看我博客的更新……</li></ul>]]></content>
    
    <summary type="html">
    
      &lt;center&gt;&lt;strong&gt;（本文为本人原创，请尊重个人劳动成果。未经本人许可，严禁转载！）&lt;/strong&gt;&lt;/center&gt;

&lt;p&gt;在这个“大数据”的时代，传统的跨平台C++库Qt已经将魔爪丧心病狂的伸向了“云计算”。在2012年的Qt开发者大会上，Qt发布了BaaS(Backend as a Service)服务——&lt;code&gt;Enginio&lt;/code&gt;，旨在为用户提供一个NoSQL数据库的后端平台。截至到（2014年9月），&lt;a href=&quot;http://qtcloudservices.com&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Qt云服务&lt;/a&gt;(Qt Cloud Services，简称“QTC”)已经发展成为了提供以下三种服务的云平台：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.qtcloudservices.com/mar/introduction&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Managed Application Runtime (MAR)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.qtcloudservices.com/eds/introduction&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Enginio Data Storage (EDS)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.qtcloudservices.com/mws/introduction&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Managed WebSocket (MWS)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
    
    </summary>
    
      <category term="开发" scheme="http://www.chenguanzhou.com/categories/%E5%BC%80%E5%8F%91/"/>
    
    
      <category term="Qt" scheme="http://www.chenguanzhou.com/tags/Qt/"/>
    
      <category term="QTC" scheme="http://www.chenguanzhou.com/tags/QTC/"/>
    
      <category term="NOSQL" scheme="http://www.chenguanzhou.com/tags/NOSQL/"/>
    
      <category term="ENGINIO" scheme="http://www.chenguanzhou.com/tags/ENGINIO/"/>
    
      <category term="云计算" scheme="http://www.chenguanzhou.com/tags/%E4%BA%91%E8%AE%A1%E7%AE%97/"/>
    
  </entry>
  
  <entry>
    <title>Windows下用VC与QT编译MPI程序入门</title>
    <link href="http://www.chenguanzhou.com/2014/04/29/2014-04-29-win-mpi/"/>
    <id>http://www.chenguanzhou.com/2014/04/29/2014-04-29-win-mpi/</id>
    <published>2014-04-29T08:52:53.000Z</published>
    <updated>2022-01-07T03:19:22.120Z</updated>
    
    <content type="html"><![CDATA[<center><strong>（本文为本人原创，请尊重个人劳动成果。未经本人许可，严禁转载！）</strong></center><p><a href="http://zh.wikipedia.org/wiki/%E8%A8%8A%E6%81%AF%E5%82%B3%E9%81%9E%E4%BB%8B%E9%9D%A2" target="_blank" rel="noopener">MPI</a>是<code>信息传递接口</code>的简称，常用来进行进程间、机器间的通信与并行计算。一般而言，MPI都会部署在*nix系统下，在Windows下面直接编译、配置MPI并不容易。本文利用MS提供的编译好的MPI的版本，介绍如何在Windows原生环境下（不包括MinGW、CygWin），使用VC或QT编译MPI程序。</p><a id="more"></a><h1 id="下载、安装MPI"><a href="#下载、安装MPI" class="headerlink" title="下载、安装MPI"></a>下载、安装MPI</h1><p>MS官网提供编译好的MPI安装程序，可以直接下载<a href="http://go.microsoft.com/fwlink/?LinkId=389563" target="_blank" rel="noopener">【传送门】</a>。下载好后，直接安装既可。</p><h1 id="使用VS编写MPI程序"><a href="#使用VS编写MPI程序" class="headerlink" title="使用VS编写MPI程序"></a>使用VS编写MPI程序</h1><h2 id="1-新建工程"><a href="#1-新建工程" class="headerlink" title="1. 新建工程"></a>1. 新建工程</h2><p>新建VC控制台工程。</p><h2 id="2-配置路径"><a href="#2-配置路径" class="headerlink" title="2. 配置路径"></a>2. 配置路径</h2><p>“项目右键→属性→配置属性→VC++目录”中，分别将MPI安装路径里的Inc与Lib路径添加到<code>包含目录</code>和<code>库目录</code>中。PS：上述Lib路径，32位环境下面是指Lib下面的i386文件夹，64位库则是指amd64文件夹。<br><img src="/images/VS_MPI.png" alt="Demo"></p><h2 id="3-配置lib文件"><a href="#3-配置lib文件" class="headerlink" title="3. 配置lib文件"></a>3. 配置lib文件</h2><p>“项目右键→属性→配置属性→链接器→输入→附加依赖项”，添加MPI的lib文件，即msmpi.lib<br><img src="/images/VS_MPI_DEBUG.png" alt="Demo"></p><h2 id="4-code"><a href="#4-code" class="headerlink" title="4. code"></a>4. code</h2><p>在cpp文件中，写入如下代码（找不到<code>stdafx.h</code>的，可以删掉第一句）：<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"stdafx.h"</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;mpi.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;string.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> BUFSIZE 128</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> TAG 0</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">char</span> *argv[])</span></span></span><br><span class="line"><span class="function"></span>&#123;</span><br><span class="line">    <span class="keyword">char</span> idstr[<span class="number">32</span>];</span><br><span class="line">    <span class="keyword">char</span> buff[BUFSIZE];</span><br><span class="line">    <span class="keyword">int</span> numprocs;</span><br><span class="line">    <span class="keyword">int</span> myid;</span><br><span class="line">    <span class="keyword">int</span> i;</span><br><span class="line">    MPI_Status stat;</span><br><span class="line">    <span class="comment">/* MPI programs start with MPI_Init; all 'N' processes exist thereafter */</span></span><br><span class="line">    MPI_Init(&amp;argc,&amp;argv);</span><br><span class="line">    <span class="comment">/* find out how big the SPMD world is */</span></span><br><span class="line">    MPI_Comm_size(MPI_COMM_WORLD,&amp;numprocs);</span><br><span class="line">    <span class="comment">/* and this processes' rank is */</span></span><br><span class="line">    MPI_Comm_rank(MPI_COMM_WORLD,&amp;myid);</span><br><span class="line"></span><br><span class="line">    <span class="comment">/* At this point, all programs are running equivalently, the rank</span></span><br><span class="line"><span class="comment">      distinguishes the roles of the programs in the SPMD model, with</span></span><br><span class="line"><span class="comment">      rank 0 often used specially... */</span></span><br><span class="line">    <span class="keyword">if</span>(myid == <span class="number">0</span>)</span><br><span class="line">    &#123;</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">"%d: We have %d processors\n"</span>, myid, numprocs);</span><br><span class="line">        <span class="keyword">for</span>(i=<span class="number">1</span>;i&lt;numprocs;i++)</span><br><span class="line">        &#123;</span><br><span class="line">            sprintf_s(buff, <span class="string">"Hello %d! "</span>, i);</span><br><span class="line">            MPI_Send(buff, BUFSIZE, MPI_CHAR, i, TAG, MPI_COMM_WORLD);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">for</span>(i=<span class="number">1</span>;i&lt;numprocs;i++)</span><br><span class="line">        &#123;</span><br><span class="line">            MPI_Recv(buff, BUFSIZE, MPI_CHAR, i, TAG, MPI_COMM_WORLD, &amp;stat);</span><br><span class="line">            <span class="built_in">printf</span>(<span class="string">"%d: %s\n"</span>, myid, buff);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span></span><br><span class="line">    &#123;</span><br><span class="line">        <span class="comment">/* receive from rank 0: */</span></span><br><span class="line">        MPI_Recv(buff, BUFSIZE, MPI_CHAR, <span class="number">0</span>, TAG, MPI_COMM_WORLD, &amp;stat);</span><br><span class="line">        sprintf_s(idstr, <span class="string">"Processor %d "</span>, myid);</span><br><span class="line">        strncat_s(buff, idstr, BUFSIZE<span class="number">-1</span>);</span><br><span class="line">        strncat_s(buff, <span class="string">"reporting for duty\n"</span>, BUFSIZE<span class="number">-1</span>);</span><br><span class="line">        <span class="comment">/* send to rank 0: */</span></span><br><span class="line">        MPI_Send(buff, BUFSIZE, MPI_CHAR, <span class="number">0</span>, TAG, MPI_COMM_WORLD);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/* MPI programs end with MPI Finalize; this is a weak synchronization point */</span></span><br><span class="line">    MPI_Finalize();</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><p>PS：这段代码中，由于VS高版本安全性能的提升，不能使用<code>sprintf</code>、<code>strncat</code>函数，因此，代码中全部被改为了<code>sprintf_s</code>与<code>strncat_s</code>。低版本的VS抱错的话，请自动改回来。</p><h2 id="5-修改调试方式"><a href="#5-修改调试方式" class="headerlink" title="5. 修改调试方式"></a>5. 修改调试方式</h2><p>由于MPI程序要能并行计算，必须由<code>mpiexec.exe</code>启动，不能直接运行程序的exe，因此需要修改程序的运行方式。“项目右键→属性→配置属性→调试”，将<code>命令</code>改为<code>mpiexec</code>，<code>工作参数</code>改为<code>$(TargetPath)</code>。<br><img src="/images/VS_MPI_LINK.png" alt="Demo"></p><h2 id="6-生成"><a href="#6-生成" class="headerlink" title="6. 生成"></a>6. 生成</h2><p>不报错即可。生成后结果如下：<br><img src="/images/VS_MPI_RESULT.png" alt="Demo"></p><h1 id="使用Qt编写MPI程序"><a href="#使用Qt编写MPI程序" class="headerlink" title="使用Qt编写MPI程序"></a>使用Qt编写MPI程序</h1><p>其实严格来说，这讲的是用QtCreator来构建，实际上编译器还是VC的。</p><h2 id="1-新建工程-1"><a href="#1-新建工程-1" class="headerlink" title="1. 新建工程"></a>1. 新建工程</h2><p>新建项目→非Qt项目→纯c++语言项目</p><h2 id="2-配置环境变量"><a href="#2-配置环境变量" class="headerlink" title="2. 配置环境变量"></a>2. 配置环境变量</h2><p>可以直接在系统环境变量中配置，也可以在Qt中的“项目→构建与运行→构建变量”中进行。具体设置如下：</p><ul><li>添加MPI安装路径里的Inc路径到环境变量<code>include</code>中（不存在则新建这个环境变量，下同）；</li><li>添加MPI的lib文件所在路径到环境变量<code>lib</code>中。（与前文一样，注意32位与64位的区别）<h2 id="3-修改pro文件"><a href="#3-修改pro文件" class="headerlink" title="3. 修改pro文件"></a>3. 修改pro文件</h2>在项目pro文件，在里面添加下面2行代码，并重新qmake：<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">LIBS += -lmsmpi</span><br><span class="line">DESTDIR = ./</span><br></pre></td></tr></table></figure></li></ul><p>第一句代表链接到msmpi.lib文件。第二句是为了后面更好的运行程序，更改了我们程序生成的路径。</p><h2 id="4-code-1"><a href="#4-code-1" class="headerlink" title="4. code"></a>4. code</h2><p>代码跟前文VS里的一样，只需把第一行去掉</p><h2 id="5-修改调试方式-1"><a href="#5-修改调试方式-1" class="headerlink" title="5. 修改调试方式"></a>5. 修改调试方式</h2><p>“项目→构建与运行→运行”设置如下图：<br><img src="/images/QT_MPI.png" alt="Demo"><br>其中，执行的是mpiexec.exe，“MPITest.exe”为程序生成的exe。这一步的目的跟VS中的一样。</p><h2 id="6-构建并运行"><a href="#6-构建并运行" class="headerlink" title="6. 构建并运行"></a>6. 构建并运行</h2><p>运行结果应该跟VS的一样</p><h1 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h1><p>MPI程序在Win下面跟普通的第三方库并没有太大区别，只是在运行的时候，需要由<br>mpiexec.exe来启动程序。由本文可以看出，文中提供Win下两种IDE编译MPI程序的方法，大同小异。</p><h1 id="参考资料"><a href="#参考资料" class="headerlink" title="参考资料"></a>参考资料</h1><ol><li><a href="http://zh.wikipedia.org/wiki/%E8%A8%8A%E6%81%AF%E5%82%B3%E9%81%9E%E4%BB%8B%E9%9D%A2" target="_blank" rel="noopener">MPI维基百科</a></li><li><a href="http://www.mpich.org/" target="_blank" rel="noopener">MPICH官网</a></li></ol>]]></content>
    
    <summary type="html">
    
      &lt;center&gt;&lt;strong&gt;（本文为本人原创，请尊重个人劳动成果。未经本人许可，严禁转载！）&lt;/strong&gt;&lt;/center&gt;


&lt;p&gt;&lt;a href=&quot;http://zh.wikipedia.org/wiki/%E8%A8%8A%E6%81%AF%E5%82%B3%E9%81%9E%E4%BB%8B%E9%9D%A2&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;MPI&lt;/a&gt;是&lt;code&gt;信息传递接口&lt;/code&gt;的简称，常用来进行进程间、机器间的通信与并行计算。一般而言，MPI都会部署在*nix系统下，在Windows下面直接编译、配置MPI并不容易。本文利用MS提供的编译好的MPI的版本，介绍如何在Windows原生环境下（不包括MinGW、CygWin），使用VC或QT编译MPI程序。&lt;/p&gt;
    
    </summary>
    
      <category term="开发" scheme="http://www.chenguanzhou.com/categories/%E5%BC%80%E5%8F%91/"/>
    
    
      <category term="Qt" scheme="http://www.chenguanzhou.com/tags/Qt/"/>
    
      <category term="MSVC" scheme="http://www.chenguanzhou.com/tags/MSVC/"/>
    
      <category term="MPI" scheme="http://www.chenguanzhou.com/tags/MPI/"/>
    
      <category term="并行计算" scheme="http://www.chenguanzhou.com/tags/%E5%B9%B6%E8%A1%8C%E8%AE%A1%E7%AE%97/"/>
    
  </entry>
  
  <entry>
    <title>QT快速读取显示SQLite3数据库数据</title>
    <link href="http://www.chenguanzhou.com/2014/01/17/2014-01-17-qtkuai-su-du-qu-xian-shi-sqlite3shu-ju-ku-shu-ju/"/>
    <id>http://www.chenguanzhou.com/2014/01/17/2014-01-17-qtkuai-su-du-qu-xian-shi-sqlite3shu-ju-ku-shu-ju/</id>
    <published>2014-01-17T08:56:16.000Z</published>
    <updated>2022-01-07T03:19:22.120Z</updated>
    
    <content type="html"><![CDATA[<center><strong>（本文为本人原创，请尊重个人劳动成果。未经本人许可，严禁转载！）</strong></center><p><code>SQLite3</code>是一个轻量级的文件数据库，拥有其他数据库无可比拟的高效率，其自身的C语言API已经能够满足大多数应用。蛋似，想要将数据直接显示在类似DataGrid控件中，光靠他自带的API可能就会遇到麻烦了。因为当数据量过大的时候，直接将所有数据数据都读到内存中来是一种低效、不靠谱的方法。此时，支持Model/View的QT就能帮上忙，快速解决这个问题。</p><a id="more"></a><h2 id="QT的SQL模块"><a href="#QT的SQL模块" class="headerlink" title="QT的SQL模块"></a>QT的SQL模块</h2><hr><p>QT SQL是QT中负责处理数据库的模块，处理数据库之前，我们先要获取数据库的连接。</p><h3 id="1-获取数据库连接"><a href="#1-获取数据库连接" class="headerlink" title="1.获取数据库连接"></a>1.获取数据库连接</h3><p>我们可以从QT文档中找到相应的API介绍：</p><blockquote><p>The <code>QSqlDatabase</code> class represents a connection to a database.</p></blockquote><p>一个<code>QSqlDatabase</code>类的对象，就是对数据库的一个连接。</p><p>我们可以通过下面的代码获取PostgreSQL数据库的连接，并打开数据库：</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">QSqlDatabase db = QSqlDatabase::addDatabase(<span class="string">"QPSQL"</span>);</span><br><span class="line">db.setHostName(<span class="string">"acidalia"</span>);</span><br><span class="line">db.setDatabaseName(<span class="string">"customdb"</span>);</span><br><span class="line">db.setUserName(<span class="string">"mojito"</span>);</span><br><span class="line">db.setPassword(<span class="string">"J0a1m8"</span>);</span><br><span class="line"><span class="keyword">bool</span> ok = db.open();</span><br></pre></td></tr></table></figure><p>其中，”QPSQL”表示的就是PostgreSQL的驱动（Driver），下面就是官方文档给出的各个驱动对应的字符串：</p><table><thead><tr><th>Driver Type</th><th style="text-align:left">Description </th></tr></thead><tbody><tr><td>QDB2</td><td style="text-align:left">IBM DB2</td></tr><tr><td>QIBASE</td><td style="text-align:left">Borland InterBase </td></tr><tr><td>QMYSQL</td><td style="text-align:left">MySQL Driver</td></tr><tr><td>QODBC</td><td style="text-align:left">ODBC Driver (includes Microsoft SQL Server)</td></tr><tr><td>QPSQL</td><td style="text-align:left">PostgreSQL Driver</td></tr><tr><td>QSQLITE</td><td style="text-align:left">SQLite version 3 or above</td></tr><tr><td>QSQLITE2</td><td style="text-align:left">SQLite version 2</td></tr><tr><td>QTDS</td><td style="text-align:left">Sybase Adaptive Server</td></tr></tbody></table><p>SQLite3并不需要设置用户名密码，因此要获取SQLite3连接的话，就得使用：</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">QSqlDatabase db = QSqlDatabase::addDatabase(<span class="string">"QSQLITE"</span>);</span><br><span class="line">db.setDatabaseName(<span class="string">"hehe.db"</span>);<span class="comment">//hehe.db就是SQLite的文件名</span></span><br></pre></td></tr></table></figure><h3 id="2-在QTableView中显示"><a href="#2-在QTableView中显示" class="headerlink" title="2.在QTableView中显示"></a>2.在QTableView中显示</h3><p>模式是QT的一大亮点，在该模式下，界面与数据分开处理，同时也增强了代码的可移植性（有关Model/VIew结构的详细信息，参见 <a href="http://www.devbean.net/2013/01/qt-study-road-2-model-view/" target="_blank" rel="noopener">这篇文章</a> ），例如，对SQLite数据库处理的算法，可以很容易的移植到SQL Server里面。QT中显示格网数据的Widget是<code>QTableView</code>，而对应的Model类则是<code>QSqlQueryModel</code>或<code>QSqlRelationalTableModel</code>，二者区别就是，前者是只读的Model，后者为可编辑的并且支持外码。</p><p>下面几句代码就可以简单的将db链接的数据库显示在<code>QTableView</code>中:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">QTableView* widget = <span class="keyword">new</span> QTableView();</span><br><span class="line">QAbstractTableModel* model = <span class="keyword">new</span>  SqlRelationalTableModel(<span class="literal">NULL</span>,db);</span><br><span class="line">model-&gt;setTable(<span class="string">"table1"</span>);<span class="comment">//"table1"为数据库中某一张表的名称</span></span><br><span class="line">model-&gt;select();<span class="comment">//执行SQL的select语句，将数据显示在QTableView中</span></span><br><span class="line">widget-&gt;setModel(model);</span><br></pre></td></tr></table></figure><h2 id="一个Demo"><a href="#一个Demo" class="headerlink" title="一个Demo"></a>一个Demo</h2><hr><p>这个demo展示一个使用QT读取SQLIte数据库的程序。这个程序中打开SQLite3数据库文件后，库内每一个表都会单独显示在一个Tab页里面。界面如图：</p><p><img src="/images/QtSqlReader.png" alt="Demo"></p><p>在QtCreator中，新建一个GUI项目，其他都选默认参数。在ui文件中，添加一个QTabWidget，并删除其中所有的tab页。同时菜单中新建一个QAction，用以选择打开文件，并设置click对应的槽函数。</p><p><code>mainwindow.h</code>:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">ifndef</span> MAINWINDOW_H</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> MAINWINDOW_H</span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;QMainWindow&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> Ui &#123;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MainWindow</span>;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MainWindow</span> :</span> <span class="keyword">public</span> QMainWindow</span><br><span class="line">&#123;</span><br><span class="line">    Q_OBJECT</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span>:</span><br><span class="line">    <span class="function"><span class="keyword">explicit</span> <span class="title">MainWindow</span><span class="params">(QWidget *parent = <span class="number">0</span>)</span></span>;</span><br><span class="line">    ~MainWindow();</span><br><span class="line"></span><br><span class="line"><span class="keyword">private</span> slots:</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">on_actionOpenSQLite3File_triggered</span><span class="params">()</span></span>;</span><br><span class="line">    <span class="function"><span class="keyword">void</span> <span class="title">ReadDB</span><span class="params">(<span class="keyword">const</span> QString &amp;fileName)</span></span>;</span><br><span class="line"><span class="keyword">private</span>:</span><br><span class="line">    Ui::MainWindow *ui;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">endif</span> <span class="comment">// MAINWINDOW_H</span></span></span><br></pre></td></tr></table></figure><p><code>mainwindow.cpp</code>:</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"mainwindow.h"</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"ui_mainwindow.h"</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;QFileDialog&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;QtSql&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;QTableView&gt;</span></span></span><br><span class="line"></span><br><span class="line">MainWindow::MainWindow(QWidget *parent) :</span><br><span class="line">    QMainWindow(parent),</span><br><span class="line">    ui(<span class="keyword">new</span> Ui::MainWindow)</span><br><span class="line">&#123;</span><br><span class="line">    ui-&gt;setupUi(<span class="keyword">this</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">MainWindow::~MainWindow()</span><br><span class="line">&#123;</span><br><span class="line">    <span class="keyword">delete</span> ui;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">void</span> MainWindow::on_actionOpenSQLite3File_triggered()</span><br><span class="line">&#123;</span><br><span class="line">    QString fileName = QFileDialog::getOpenFileName(<span class="keyword">this</span>,tr(<span class="string">"Open a SQLite3 File"</span>),QString(),<span class="string">"DB (*.db);;All files(*.*)"</span>);</span><br><span class="line">    <span class="keyword">if</span> (fileName.isEmpty())</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    ReadDB(fileName);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">void</span> MainWindow::ReadDB(<span class="keyword">const</span> QString &amp;fileName)</span><br><span class="line">&#123;</span><br><span class="line">    QSqlDatabase db = QSqlDatabase::addDatabase(<span class="string">"QSQLITE"</span>);</span><br><span class="line">    db.setDatabaseName(fileName);</span><br><span class="line">    <span class="keyword">if</span> (!db.open())</span><br><span class="line">        <span class="keyword">return</span>;</span><br><span class="line">    ui-&gt;tabWidget-&gt;clear();</span><br><span class="line">    <span class="function">QSqlQuery <span class="title">query</span><span class="params">(<span class="string">"Select tbl_name From sqlite_master"</span>)</span></span>;</span><br><span class="line">    QStringList tableList;</span><br><span class="line">    <span class="keyword">while</span> (query.next()) &#123;</span><br><span class="line">        tableList &lt;&lt; query.value(<span class="number">0</span>).toString();</span><br><span class="line">    &#125;</span><br><span class="line">    foreach (QString tableName, tableList) &#123;</span><br><span class="line">        QTableView* widget = <span class="keyword">new</span> QTableView(ui-&gt;tabWidget);</span><br><span class="line">        QSqlRelationalTableModel* model = <span class="keyword">new</span> QSqlRelationalTableModel(<span class="literal">NULL</span>,db);</span><br><span class="line">        model-&gt;setTable(tableName);</span><br><span class="line">        model-&gt;select();</span><br><span class="line">        widget-&gt;setModel(model);</span><br><span class="line">        ui-&gt;tabWidget-&gt;addTab(widget,tableName);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h2 id="常见问题"><a href="#常见问题" class="headerlink" title="常见问题"></a>常见问题</h2><hr><p>1.</p><blockquote><p>打开文件后，TableView没有显示，并且输出窗口输出以下字符串：<br>QSqlDatabase: QSQLITE driver not loaded<br>QSqlDatabase: available drivers: QPSQL7 QPSQL QODBC3 QODBC</p></blockquote><p>这说明QT没有找到sqlite的插件，这个插件一般在QT_DIR/plugins/sqldrivers，windows系统下的debug与release版插件分别为：<code>qsqlited4.dll</code>与<code>qsqlite4.dll</code>。原因有两个，一是qt本身并没有带这个插件，需要从源码编译；二是QT并未找到plugins所在目录，这需要设置<code>QT_PLUGIN_PATH</code>环境变量为插件目录（例如C:\OSGeo4W64\apps\Qt4\plugins）。</p><p>2.</p><blockquote><p>打开文件后，TableView没有显示，并且没有输出上述字符串</p></blockquote><p>QT的sqlite插件还依赖于sqlite3.dll（Windows系统下），可将该dll放到程序所在目录下，或者PATH路径下</p>]]></content>
    
    <summary type="html">
    
      &lt;center&gt;&lt;strong&gt;（本文为本人原创，请尊重个人劳动成果。未经本人许可，严禁转载！）&lt;/strong&gt;&lt;/center&gt;

&lt;p&gt;&lt;code&gt;SQLite3&lt;/code&gt;是一个轻量级的文件数据库，拥有其他数据库无可比拟的高效率，其自身的C语言API已经能够满足大多数应用。蛋似，想要将数据直接显示在类似DataGrid控件中，光靠他自带的API可能就会遇到麻烦了。因为当数据量过大的时候，直接将所有数据数据都读到内存中来是一种低效、不靠谱的方法。此时，支持Model/View的QT就能帮上忙，快速解决这个问题。&lt;/p&gt;
    
    </summary>
    
      <category term="开发" scheme="http://www.chenguanzhou.com/categories/%E5%BC%80%E5%8F%91/"/>
    
    
      <category term="Qt" scheme="http://www.chenguanzhou.com/tags/Qt/"/>
    
      <category term="SQLite" scheme="http://www.chenguanzhou.com/tags/SQLite/"/>
    
      <category term="MVC" scheme="http://www.chenguanzhou.com/tags/MVC/"/>
    
      <category term="数据库" scheme="http://www.chenguanzhou.com/tags/%E6%95%B0%E6%8D%AE%E5%BA%93/"/>
    
  </entry>
  
</feed>
