Pyqt5实战—获取省/市/区矢量数据
python有两个用于制作GUI界面的包,twinker和Pyqt5。其中Pyqt5可以结合Qt designer使用,制作界面简单方便,交互性强,因此笔者打算入门Pyqt5。“纸上得来终觉浅,绝知此事要躬行”。笔者始终奉行这句话,因此笔者拟实践几个小例子,从而更快速的入门。
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> <style type="text/css"> body, html,#allmap {width: 100%;height: 100%;overflow: hidden;margin:0;font-family:"微软雅黑";} #panel{ position:absolute; left:5px; top:5px; } #result{ background: #fff; padding:5px; } </style> <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script> <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=1XjLLEhZhQNUzd93EjU5nOGQ"></script> <title>添加行政区划</title> </head> <body> <div id="allmap"></div> <div id="panel"> <div> <input type="text" id="keyword" value="昆明市"/> <input type="button" value="查看范围" id="commitBtn"/> 边界经纬度坐标 <textarea id="pathStr"></textarea> 边界墨卡托坐标 <textarea id="pathMc"></textarea> </div> <div id="result"> </div> </div> </body> </html> <script type="text/javascript"> // 百度地图API功能 var map = new BMap.Map("allmap"); map.centerAndZoom(new BMap.Point(116.403765, 39.914850), 5); map.enableScrollWheelZoom(); var mercatorProjection = map.getMapType().getProjection(); $("#commitBtn").bind('click', function(){ getBoundary($("#keyword").val()); }); function getBoundary(city){ var bdary = new BMap.Boundary(); bdary.get(city, function(rs){ //获取行政区域 map.clearOverlays(); //清除地图覆盖物 var count = rs.boundaries.length; //行政区域的点有多少个 if (count === 0) { alert('未能获取当前输入行政区域'); return ; } var pointArray = []; for (var i = 0; i < count; i++) { var ply = new BMap.Polygon(rs.boundaries[i], {strokeWeight: 2, strokeColor: "#ff0000"}); //建立多边形覆盖物 map.addOverlay(ply); //添加覆盖物 pointArray = pointArray.concat(ply.getPath()); } var pathStr = ""; var pathMc = ""; for (var i = 0; i < pointArray.length; i++) { var mc = mercatorProjection.lngLatToPoint(pointArray[i]); pathStr += pointArray[i].lng + "," + pointArray[i].lat + ";"; pathMc += mc.x + "," + mc.y + ";"; } $('#pathStr').html(pathStr); $('#pathMc').html(pathMc); var ply = new BMap.Polygon(pointArray , {strokeWeight: 2, strokeColor: "#ff0000"}); //建立多边形覆盖物 var bounds = ply.getBounds(); var ne = bounds.getNorthEast(); var sw = bounds.getSouthWest(); var neMc = mercatorProjection.lngLatToPoint(ne); var swMc = mercatorProjection.lngLatToPoint(sw); var str = "经纬度:左下角,右上角:" + sw.lng + "," + sw.lat + ";" + ne.lng + "," + ne.lat + "<br/>墨卡托坐标:左下角,右上角:" + swMc.x + "," + swMc.y + ";" + neMc.x + "," + neMc.y; $('#result').html(str); console.log(bounds); map.setViewport(pointArray); //调整视野 }); } //getBoundary('北京'); </script>
我们可以通过这个html页面,查询省市的边界经纬度坐标。众所周知,边界都是由众多点坐标组成的。这里选择经纬度坐标,拷贝到txt文件中。
def convert_to_shp(self): poi_file = self.lineEdit.text() #lineEdit/lineEdit_2是两个文本框的名称,lineEdit.text读取输入的文本信息 outputfile = self.lineEdit_2.text() p_lon =[] p_lat =[] with open(poi_file,'r') as file_obj: #读取点坐标 lines = file_obj.read() lines = str(lines) lines = lines.split(';') for i in range(len(lines)): lon = lines[i].split(',')[0] lat = lines[i].split(',')[1] p_lon.append(lon) p_lat.append(lat) driver = ogr.GetDriverByName('ESRI Shapefile') ds = driver.CreateDataSource(outputfile) #创建矢量数据集 srs = osr.SpatialReference() srs.ImportFromEPSG(4326) layer = ds.CreateLayer('tempfile', srs, ogr.wkbPolygon) layer.CreateField(ogr.FieldDefn('lat', ogr.OFTReal)) #创建字段 layer.CreateField(ogr.FieldDefn('lon', ogr.OFTReal)) ring = ogr.Geometry(ogr.wkbLinearRing) feature = ogr.Feature(layer.GetLayerDefn()) for i in range(len(lines)): feature.SetField('lon', p_lon[i]) feature.SetField('lat', p_lat[i]) ring.AddPoint(float(p_lon[i]), float(p_lat[i])) layer.CreateFeature(feature) #每次都新增要素到图层 poly = ogr.Geometry(ogr.wkbPolygon) poly.AddGeometry(ring) feature.SetGeometry(poly) layer.CreateFeature(feature) del ds msg_box = QtWidgets.QMessageBox msg_box.information(self,"提醒","已成功生成shp文件。",msg_box.Yes | msg_box.No) #提示功能完成
# -*- coding: utf-8 -*- from PyQt5 import QtCore, QtGui, QtWidgets class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(800, 600) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.pushButton = QtWidgets.QPushButton(self.centralwidget) self.pushButton.setGeometry(QtCore.QRect(210, 260, 71, 21)) self.pushButton.setObjectName("pushButton") self.lineEdit = QtWidgets.QLineEdit(self.centralwidget) self.lineEdit.setGeometry(QtCore.QRect(180, 90, 161, 21)) self.lineEdit.setObjectName("lineEdit") self.lineEdit_2 = QtWidgets.QLineEdit(self.centralwidget) self.lineEdit_2.setGeometry(QtCore.QRect(180, 170, 161, 21)) self.lineEdit_2.setObjectName("lineEdit_2") self.label = QtWidgets.QLabel(self.centralwidget) self.label.setGeometry(QtCore.QRect(110, 90, 51, 21)) self.label.setObjectName("label") self.label_2 = QtWidgets.QLabel(self.centralwidget) self.label_2.setGeometry(QtCore.QRect(110, 170, 51, 20)) self.label_2.setObjectName("label_2") MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 18)) self.menubar.setObjectName("menubar") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) self.pushButton.setText(_translate("MainWindow", "开始")) self.label.setText(_translate("MainWindow", "输入文件")) self.label_2.setText(_translate("MainWindow", "输出文件名"))
接着编写run.py用于调用UI界面,这一步是重中之重,你可以读不懂ui界面的代码,但是你必须懂run.py的代码。
import sys from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow from PyQt5 import QtWidgets from convert_shp import Ui_MainWindow from osgeo import ogr, osr class mwindow(QtWidgets.QMainWindow, Ui_MainWindow): def __init__(self): super(mwindow, self).__init__() self.setupUi(self) def convert_to_shp(self): pass if __name__ == '__main__': app = QApplication(sys.argv) w = mwindow() w.pushButton.clicked.connect(w.convert_to_shp) #把button和convert_to_shp事件链接到一起 w.show() sys.exit(app.exec_())
做好了run.py、main.py,我们可以用Pyinstaller打包成exe文件。pyinstaller -F demo.py
Bug调试:
AttributeError: 'mywindow' object has no attribute 'setCentralWidget'
https://blog.csdn.net/oMoDao1/article/details/85285642