bravo's blog

多分ググっても出てこないようなプログラミング記事を目指します!

PyQtでの2Dグラフィックス その1 (QWidgetに直接描画する)

PyQtでの描画処理について

PyQtでグラフィックス処理をするには、主に以下のような方法があります。

  • QWidgetの描画処理をオーバーライド:単純なグラフィック描画や自作のウィジェットとして描画する
  • QGraphicsItemの使用:Qtに備わった複数のグラフィックを扱うフレームワーク
  • OpenGLを使用:OpenGLの命令を使う場合(執筆時点では未調査、存在確認だけです。)

QWidgetに直接描画する

paintEventメソッドのオーバーライド

QWidgetやQWidgetから派生したクラスでは、実際に描画する処理がpaintEvent()メソッドで行われます。 また、描画内容を変えたい時にはupdate()メソッドを呼び出すと、QWidget側が適切に更新します。

実際の描画は、painteEvent()内でQPainterやQPainterPathのインスタンスを生成し、描画命令をするだけです。 単純に線を引くdrawLine()や、連続した線を引くdrawPolyline()、長方形を描画するdrawRect()、などがあります。 描画命令は種類が豊富なので、公式のAPIが載ったドキュメントを参照ください。 検索サイト等で「QPainter (バージョン番号)」や「QPainterPath (バージョン番号)」で検索すればすぐに出てくると思います。

正方形を描画するサンプル

赤い線と黄色い塗りの正方形を描画します。

import sys

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class Widget(QWidget):
    def __init__(self, parent=None):
        super(Widget, self).__init__(parent)

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setPen(Qt.red)
        painter.setBrush(Qt.yellow)
        painter.drawRect(10, 10, 100, 100)

def main():
    app = QApplication(sys.argv)
    w = Widget()
    w.show()
    w.raise_()
    app.exec_()

if __name__ == '__main__':
    main()

実行結果
f:id:bravo:20160207080309p:plain

マウスで描画するサンプル

真っ白なQWidgetを用意し、マウスでドラッグしている間に線を描画します。

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class Widget(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.px = None
        self.py = None
        self.points = []
        self.psets = []

    def mousePressEvent(self, event):
        self.points.append(event.pos())
        self.update()

    def mouseMoveEvent(self, event):
        self.points.append(event.pos())
        self.update()

    def mouseReleaseEvent(self, event):
        self.pressed = False
        self.psets.append(self.points)
        self.points = []
        self.update()

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setPen(Qt.NoPen)
        painter.setBrush(Qt.white)
        painter.drawRect(self.rect())

        painter.setPen(Qt.black)

        # draw historical points
        for points in self.psets:
            painter.drawPolyline(*points)

        # draw current points
        if self.points:
            painter.drawPolyline(*self.points)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = Widget()
    w.show()
    w.raise_()
    sys.exit(app.exec_())

実行結果(描画部分はマウスで操作しています)
f:id:bravo:20160207082701p:plain

PR