Created
November 19, 2015 23:39
-
-
Save peace098beat/db002e83002cc16c7981 to your computer and use it in GitHub Desktop.
[PySide] QPainterのスケルトンコード
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! coding:utf-8 | |
""" | |
pyside-painter-skelton.py | |
pysideでグラフィックを描画するためのスケルトンコード | |
Created by 0160929 on 2015/11/19 7:28 | |
""" | |
__version__ = '0.3' | |
import sys | |
import os | |
# PySide系モジュール | |
from PySide.QtGui import * | |
from PySide.QtCore import * | |
# 演算系モジュール | |
import numpy as np | |
# logを保存 | |
from datetime import datetime | |
import csv | |
def resetlog(file): | |
if os.path.exists(file): | |
os.remove(file) | |
# ログファイルを削除 | |
resetlog('log.cav') | |
def debuglog(s=None, data=None): | |
d = datetime.now().isoformat() | |
with open('log.csv', 'a') as f: | |
writer = csv.writer(f, lineterminator='\n') | |
if not s is None: | |
writer.writerow([d, s]) | |
print d, s | |
if not data is None: | |
writer.writerow([d, data]) | |
print d, data | |
return | |
# 描画用PySideクラス | |
class GameWindow(QWidget): | |
# -- 定数(画面サイズ) ----------------- | |
SCREEN_HEIGHT = 500 | |
SCREEN_WIDTH = 700 | |
MARGIN_HEIGHT = 50 | |
MARGIN_WIDTH = 50 | |
STAGE_HEIGHT = SCREEN_HEIGHT - 2 * MARGIN_HEIGHT | |
STAGE_WIDTH = SCREEN_WIDTH - 2 * MARGIN_WIDTH | |
# -- 定数(タイマー ms) ------------------- | |
INTERVAL_TIME = 1 | |
# -- 定数(その他) --------------------- | |
def __init__(self, parent=None): | |
QWidget.__init__(self, parent) | |
self.resize(self.SCREEN_WIDTH, self.SCREEN_HEIGHT) | |
# -- 定数 ---------------------------- | |
self.step = 0 | |
# -- 画面バッファ -------------------- | |
self.pixmap = QPixmap(self.size()) | |
# -- 解析用オブジェクト -------------- | |
# -- 操作用変数 ---------------------- | |
# -- 初期画面の準備 ------------------ | |
self.refreshPixmap() # 画面バッファの初期化 | |
painter = QPainter(self.pixmap) | |
self.drawGrid(painter) # グリッドの表示 | |
self.update() | |
# メインループの準備と開始 | |
# ------------------------- | |
if False: | |
self.timer = QTimer() | |
self.timer.timeout.connect(self.mainloop) | |
self.timer.start(self.INTERVAL_TIME) | |
# ************************************************************* # | |
# メインループ | |
# ************************************************************* # | |
def mainloop(self): | |
""" | |
アニメーションのメインループ | |
アルゴリズムの時間更新等はここで行う | |
""" | |
self.step += 1 | |
# -- アルゴリズム処理----------- | |
# -- 描画 ---------------------- | |
painter = QPainter(self.pixmap) | |
self.drawGrid(painter) | |
self.drawGeoPoints(painter) | |
# -- 画面更新 (AppのタイミングでpaintEventが呼ばれる) --- | |
self.update() | |
def paintEvent(self, *args, **kwargs): | |
# -- おまじない --------------------------- | |
painter = QStylePainter(self) # QPainterを生成 | |
painter.setRenderHint(QPainter.Antialiasing, True) # アンチエイリアス | |
painter.drawPixmap(0, 0, self.pixmap) # QPainterでバッファに準備したデータを描画 | |
# 描画用QPenのデフォルト | |
pen_default = QPen() | |
pen_default.setColor(Qt.black) | |
pen_default.setWidth(2) | |
painter.setPen(pen_default) | |
brush_default = QBrush(Qt.red, Qt.NoBrush) | |
painter.setBrush(brush_default) | |
# -- アクセス用定数 ----------------------- | |
x, y = 0, 1 | |
# -- 車両の位置情報を取得 ----------------- | |
pos = self.locateXY([self.STAGE_WIDTH / 2., self.STAGE_HEIGHT / 2.]) | |
# -- 車両位置のプロット ------------------- | |
pen = QPen(Qt.red, 5) | |
painter.setPen(pen) | |
painter.drawPoint(pos[x], pos[y]) | |
# -- 車両位置に 円を描画 ----------------------------- | |
pen = QPen(Qt.black, 1, Qt.DotLine, Qt.RoundCap, Qt.RoundJoin) | |
painter.setPen(pen) | |
painter.setBrush(QBrush(QColor(0, 255, 0, 175))) | |
circle_size = 50 | |
painter.drawEllipse(pos[x] - circle_size / 2, pos[y] - circle_size / 2, circle_size, circle_size) | |
# -- 車両位置に四角を描画 ----------------------------- | |
pen = QPen(Qt.black, 1, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin) | |
painter.setPen(pen) | |
painter.setBrush(QBrush(QColor(0, 255, 0, 255), Qt.NoBrush)) | |
painter.drawRect(pos[x] - circle_size / 2, pos[y] - circle_size / 2, circle_size, circle_size) | |
# qpoints = [QPoint(*lv) for lv in v] | |
# polygon = QPolygon(qpoints) | |
# painter.drawPolygon(polygon) | |
# -- 進行方向(速度ベクトル)を描画 --------- | |
pen = QPen(Qt.gray, 1, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin) | |
painter.setPen(pen) | |
painter.drawLine(pos[x], pos[y], (pos[x] + 50), (pos[y] + 50)) | |
# -- 棒グラフを表示 ------------------------- | |
r = QRect(0, 0, 20, 30) | |
r.setHeight(200) | |
p0 = self.locateXY([20, 20], 'qp') | |
r.moveBottomLeft(p0) | |
painter.setBrush(QBrush(Qt.green, Qt.Dense4Pattern)) | |
painter.drawRect(r) | |
# ************************************************************* # | |
# 描画系補助関数 | |
# ************************************************************* # | |
def drawDebugLog(self, painter): | |
pass | |
def drawGrid(self, painter): | |
""" マップを表示する関数 | |
""" | |
# -- 定数 --------------------------------------- | |
Nx = 10 | |
Ny = 10 | |
Lx = self.STAGE_WIDTH | |
Ly = self.STAGE_HEIGHT | |
# -- 線の色と種類の選定 -------------------------- | |
painter.setPen(QPen(Qt.black, 0.5)) | |
painter.setBrush(QBrush(QColor(200, 200, 200, 150), Qt.Dense1Pattern)) | |
# -- 横線を描画 ---------------------------------- | |
for xi in range(Nx + 1): | |
p1 = self.locateXY([xi * Lx / Nx, 0], 'qp') | |
p2 = self.locateXY([xi * Lx / Nx, Ly], 'qp') | |
painter.drawLine(p1, p2) | |
# -- 縦線を描画 ---------------------------------- | |
for yi in range(Ny + 1): | |
p1 = self.locateXY([0, yi * Ly / Ny], 'qp') | |
p2 = self.locateXY([Lx, yi * Ly / Ny], 'qp') | |
painter.drawLine(p1, p2) | |
def locateXY(self, pos, type='np'): | |
""" | |
オブジェクトのローカル座標を、スクリーン上の座標へ変換 | |
""" | |
_pos = np.asarray(pos) | |
local_x, local_y = _pos.copy() | |
srn_x = local_x + self.MARGIN_WIDTH | |
srn_y = (self.SCREEN_HEIGHT - local_y - self.MARGIN_HEIGHT) | |
if type is 'np': | |
return np.asarray([srn_x, srn_y]) | |
elif type is 'qp': | |
return QPoint(srn_x, srn_y) | |
elif type is 'qpF': | |
return QPointF(srn_x, srn_y) | |
elif type is 'list': | |
return [srn_x, srn_y] | |
return 'ERROR:: check type option' | |
def locateVec(self, vec, type='np'): | |
""" | |
オブジェクトのベクトルを、スクリーン上の座標空間へ変換 | |
(※yを反転させるだけ) | |
""" | |
srn_vec = [vec[0], -1 * vec[1]] | |
if type is 'np': | |
return np.asarray(srn_vec) | |
elif type is 'qp': | |
return QPoint(*srn_vec) | |
elif type is 'qpF': | |
return QPointF(*srn_vec) | |
elif type is 'list': | |
return srn_vec | |
return 'ERROR:: check type option' | |
# ************************************************************* # | |
# その他Qt関連補助関数 | |
# ************************************************************* # | |
def refreshPixmap(self): | |
""" | |
画面バッファの初期化関数 | |
""" | |
# 画面バッファの初期化 | |
self.pixmap = QPixmap(self.size()) | |
# 画面を塗りつぶし (おまじない) | |
self.pixmap.fill(self, 0, 0) | |
self.pixmap.fill(Qt.white) | |
# ぺインターの生成 (おまじない) | |
painter = QPainter(self.pixmap) | |
# ぺインターによる初期化 (おまじない) | |
painter.initFrom(self) | |
pass | |
def sizeHint(self): | |
return QSize(self.SCREEN_WIDTH, self.SCREEN_HEIGHT) | |
def keyPressEvent(self, event): | |
e = event.key() | |
if e == Qt.Key_Up: | |
pass | |
elif e == Qt.Key_Down: | |
pass | |
elif e == Qt.Key_Left: | |
pass | |
elif e == Qt.Key_Right: | |
pass | |
elif e == Qt.Key_Plus: | |
pass | |
elif e == Qt.Key_Minus: | |
pass | |
elif e == Qt.Key_Q: | |
self.close() | |
else: | |
pass | |
print 'Presskey', e | |
self.update() | |
# ******************************************************* | |
# main関数 | |
# ******************************************************* | |
def mainGUI(): | |
app = QApplication(sys.argv) | |
win = GameWindow() | |
win.show() | |
sys.exit(app.exec_()) | |
if __name__ == "__main__": | |
mainGUI() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment