PythonとQtでListView

VisualStudio等で開発しているとおなじみのListView

clip_8

これをQTで実現するにはQTreeViewを使用する。

QtデザイナでダイアログにTreeViewを配置して以下のコードを実装。

        model = QStandardItemModel(0,3)
        model.setHeaderData( 0, Qt.Horizontal, ('名称').decode('utf-8'))
        model.setHeaderData( 1, Qt.Horizontal, ('都道府県').decode('utf-8'))
        model.setHeaderData( 2, Qt.Horizontal, ('自治体').decode('utf-8'))

        self.ui.treeView.setRootIsDecorated(False)
        self.ui.treeView.setItemsExpandable(False)
        self.ui.treeView.setModel(model)
        # view.setUniformRowHeights(True)
        model.setItem( 0, 0, QStandardItem(("山田花子").decode('utf-8')))
        model.setItem( 0, 1, QStandardItem(("東京都").decode('utf-8')))
        model.setItem( 0, 2, QStandardItem(("豊島区").decode('utf-8')))
        model.setItem( 1, 0, QStandardItem(("斉藤淳").decode('utf-8')))
        model.setItem( 1, 1, QStandardItem(("埼玉県").decode('utf-8')))
        model.setItem( 1, 2, QStandardItem(("所沢市").decode('utf-8')))

clip_10

Python メモ

文字列に変換

str(変数)

配列(リスト)


初期化

lists = []
list = ["taro","hanako"]

追加

lists.append("saito")

繰り返し

for l in lists:
    print l

よくあるインデックスをインクリメントしながらの繰り返し(idx=0から10)

for idx in Range(0, 10):
    print idx

PythonでQgsMapCanvasItemの派生クラスを作成

QgsMapCanvasItemとは

QgsMapCanvasItemはQgsMapCanvas上に固定表示されるクラス

QgsMapCanvasItemからさ区政されたクラスにはQgsPointRotationItem、QgsAnnotationItem、QgsVertexMarker がある。

QGISメニューの文字注記、HTMLアノテーション等が該当するクラス。

clip_7

QgsMapCanvasItemからの派生

今回はQgsMapCanvasItemから派生したCopyrightItemを作成して地図上にCopyrightを表示
ポイントとしては基底クラスであるQGraphicsItemのメンバー変数にDataに文字列「AnnotationItem」をセット
これがないと描画されない。
またメンバー関数paintを可変引数にすること。
QgsMapCanvasItemには引数が異なるpaint関数が存在する。
これに対応するために。

# -*- coding: utf-8 -*-
# Import the PyQt and QGIS libraries
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *
from qgis.gui import *

class CopyrightItem(QgsMapCanvasItem): 
    def __init__(self, canvas): 
        QgsMapCanvasItem.__init__(self, canvas)
        self.center = QgsPoint(0, 0)
        self.size   = 100
        self.canvas = canvas
        super(CopyrightItem,self).setData(0,"AnnotationItem")

    def setCenter(self, center): 
        self.center = center

    def center(self):
        return self.center

    def setSize(self, size):
        self.size = size 

    def size(self):
        return self.size

    def boundingRect(self):
        return QRectF(self.center.x() - self.size/2, self.center.y() - self.size/2, self.center.x() + self.size/2, self.center.y() + self.size/2)

    def paint(self, painter, *args):
        painter.drawText(200,200, "CopyrightItem")

    def updatePosition(self):
        self.setCenter(self.center)



PythonとQtでダイアログ表示

Pythonを使ってQGISのプラグインを作るにあたり、QTダイアログについて調べる

QTデザイナを起動して「新規作成」→「Dialog without Buttons」を選択。
clip_2

ボタンを配置し、ui_sampleDlg.uiに保存。

clip_4

pyuic4を使用してuiファイルをPythonファイルに変換

pyuic4 ui_sampleDlg.ui -o ui_sampleDlg.py

※pyuic4.batを使うためにC:\OSGeo4W\binにPATHを通す。
環境変数PYTHONHOMEが設定されていなければpyuic4.batに以下の行を追加

SET PYTHONHOME=C:\OSgeo4w\apps\Python27

変換後のui_sampleDlg.py

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'ui_sampleDlg.ui'
#
# Created: Sat Apr 23 07:01:53 2016
#      by: PyQt4 UI code generator 4.11.3
#
# WARNING! All changes made in this file will be lost!

from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName(_fromUtf8("Dialog"))
        Dialog.resize(400, 300)
        self.pushButton = QtGui.QPushButton(Dialog)
        self.pushButton.setGeometry(QtCore.QRect(300, 20, 75, 23))
        self.pushButton.setObjectName(_fromUtf8("pushButton"))

        self.retranslateUi(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        Dialog.setWindowTitle(_translate("Dialog", "Dialog", None))
        self.pushButton.setText(_translate("Dialog", "PushButton", None))

作成したユーザーインターフェイスを呼び出すクラスをQDialogから派生して作成
クラス名はSampleDlg、ファイル名はSampleDlg.pyとする。
※ifaceは

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'DlgTest.ui'
#
# Created: Wed Apr 20 16:59:11 2016
#      by: PyQt4 UI code generator 4.11.3
#
# WARNING! All changes made in this file will be lost!

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *
from ui_sampleDlg import Ui_Dialog

class SampleDlg(QDialog):

    def __init__(self, iface):
        QDialog.__init__(self)
        self.iface = iface
        self.ui = Ui_Dialog()
        self.ui.setupUi(self)

プラグインからSampleDlgクラスの表示

from SampleDlg import SampleDlg
dlg = SampleDlg(self.iface)
dlg.show()
dlg.exec_() 

以上で正しく表示される

clip_5

次はボタンが押されたらダイアログを閉じるように設定

SampleDlgクラスでボタンのシグナル引っ掛けてダイアログのcloseを呼ぶ

class SampleDlg(QDialog):

    def __init__(self, iface):
        ・・・
        QObject.connect(self.ui.pushButton, SIGNAL("clicked()"), self.pushButton)

    @pyqtSlot()
    def pushButton(self):
        self.close()

以上で終了

QGIS(pythonでpostgresql)

以下はまんま「stackexchange」です。
忘れないようにコピー。
How to perform SQL queries and get results from QGIS python console?

8
down vote
accepted
1) With PyQt4.QtSql: Gary Sherman shows how to query a spatial table in Creating a PostgreSQL Connection From a QGIS Layer Datasource:

from PyQt4.QtSql import *
layer = iface.activeLayer()
uri = QgsDataSourceURI()
uri.setConnection(“localhost”, “5432”, “testpostgis”, “me”, “”)
uri.setDataSource(“public”, “teststrati”, “the_geom”)
# add the layer to the canvas
vlayer = QgsVectorLayer(uri.uri(), “tot”, “postgres”)
# now query the table
db = QSqlDatabase.addDatabase(“QPSQL”);
db.setDatabaseName(uri.database())
db.setPort(int(uri.port()))
db.setUserName(uri.username())
db.setPassword(uri.password())
db.open()
# query the table
query = db.exec_(“””select * from teststrati”””)
query.next()
query.value(0)
130
# etc read the documentation of QtSQL
And you can open all the other tables/views (spatial or non spatial) similarly:

db = QSqlDatabase.addDatabase(“QPSQL”)
db.setHostName(“localhost”)
db.setPort(5432)
# non spatial table or view
db.setDatabaseName(“people”)
db.setUserName(“me”)
db.setPassword(“”)
query = QSqlQuery(db)
query.exec_(“select * from people;”)
# etc.
2) Or you can use the standard Python module for PostgreSQL/PostGIS: Psycopg2:

import psycopg2
conn = psycopg2.connect(“dbname=’testpostgis’host=’localhost’ user=’me'”)
cur = conn.cursor()
sql = “””SELECT “DIP_DIR”,”DIP”, ST_AsGeoJSON(the_geom) from teststrati;”””
cur.execute(sql)
result = cur.fetchone()
print result
(130, 30, u'{“type”:”Point”,”coordinates”:[272070.600040999997873,155389.387920000008307]}’)
With a non spatial table or view and the result as a dictionary:

conn = psycopg2.connect(“dbname=’testpostgis’host=’localhost’ user=’me'”)
dict_cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
dict_cur.execute(“””SELECT * from people;”””)
rec = dict_cur.fetchone()
rec.keys()
[‘name’, ‘id’]
rec.values()
(‘Jon Doe’,1)
# etc read the documentation of the module

カテゴリー: QGIS

QGIS(Pythonでログ出力)

class HelloWorld:
    def __init__(self, iface):
        # Save reference to the QGIS interface
        self.iface = iface
        self.canvas = iface.mapCanvas()
        QgsMessageLog.logMessage("__init__", 'HelloWorld', QgsMessageLog.INFO)

QGISのログパネルに出力される
無題

QGIS3ではこんなかんじ

from qgis.core import Qgis, QgsMessageLog
import configparser
import os

#======================================================================
# ログクラス
#======================================================================
class Trace:
    def __init__(self):
        print('init')
    @staticmethod
    def info(tag, msg):
        QgsMessageLog.logMessage(msg, tag, Qgis.Info)

カテゴリー: QGIS

QGISのログ(QgsDebugMsg)を有効にする

QGISのソースを確認すると「QgsDebugMsg」で多くのログが吐かれている。
これはQGISの内部の動作を追うには大変参考になる。
※レンダリング関係はデバッカーで追うのは大変。

実際にqgslogger.cppを確認すると下記の環境変数を設定する必要がある。
QGIS_DEBUG:1
QGIS_LOG_FILE:ログファイルのフルパス
※QGIS_DEBUG_FILEは不明

int QgsLogger::sDebugLevel = -999; // undefined value
int QgsLogger::sPrefixLength = -1;
QString QgsLogger::sFileFilter;
QString QgsLogger::sLogFile;
QTime QgsLogger::sTime;

void QgsLogger::init()
{
  if ( sDebugLevel != -999 )
    return;

  sTime.start();

  sLogFile = getenv( "QGIS_LOG_FILE" ) ? getenv( "QGIS_LOG_FILE" ) : "";
  sFileFilter = getenv( "QGIS_DEBUG_FILE" ) ? getenv( "QGIS_DEBUG_FILE" ) : "";
  sDebugLevel = getenv( "QGIS_DEBUG" ) ? atoi( getenv( "QGIS_DEBUG" ) ) :
#ifdef QGISDEBUG
                1
#else
                0
#endif
                ;

  sPrefixLength = sizeof( CMAKE_SOURCE_DIR );
  if ( CMAKE_SOURCE_DIR[sPrefixLength-1] == '/' )
    sPrefixLength++;
}

void QgsLogger::logMessageToFile( const QString& theMessage )
{
  if ( sLogFile.isEmpty() )
    return;

  //Maybe more efficient to keep the file open for the life of qgis...
  QFile file( sLogFile );
  if ( !file.open( QIODevice::Append ) )
    return;
  file.write( theMessage.toLocal8Bit().constData() );
  file.write( "\n" );
  file.close();
}

qgis起動バッチ(qgis.bat)に以下を記述してQGISを起動すると指定されたログが出力される

set QGIS_LOG_FILE=C:\QGIS\log.txt
set QGIS_DEBUG=1
カテゴリー: QGIS

PostGIS 空間インデックス

空間インデックスの作成
create index インデックス名 on テーブル名 using GIST(ジオメトリ項目名);
※テーブル名に大文字があるとテーブル名の前後にダブルコーテーションが付く。
そのような時はcreate index文でもテーブル名の前後にインデックスを付与する。
例)create index インデックス名 on “テーブル名” using GIST(ジオメトリ項目名);

空間インデックスの一覧
空間インデックスの一覧機能はないので、テーブル「pg_indexes」を参照してインデックスの女王を求める。
※psqlのコマンド\diでは表示されない

DMデータをShapeに変換

DM(数値地形図)データをArcGISで利用するにはArcToolBoxの変換ツールでジオデータベース等に変換して利用

clip_2

詳細はArcGISブログを参照

DM(数値地形図)データをShapeに変換するには国土地理院が提供している公共測量ビューア・コンバータを利用する。

公共測量ビューア・コンバータをダウンロードしたら解凍してPSEA.exeを起動しインポートメニューより対象データを指定

clip_4

座標系を指定してインポート

clip_7

インポート後エクスポートでShapeに変換