mieki256's diary



2016/10/13(木) [n年前の日記]

#2 [python] PySideでマウスを動かしてお絵かき

Windows10 x64 + Python 2.7.11 + PySide 1.2.4 で、ウインドウ上でマウスを動かすと何かを描ける、てな処理を QGraphics* を使って試してみたり。

_drawing_pyside_4.py
_ball.png
"""
PySideでウインドウに描画。
マウスを動かしてお絵かきできる。
QGraphics* を使う。

ヲドリテヒヅル PyQtでイメージビューワ
http://melpystudio.blog82.fc2.com/blog-entry-138.html
"""


import sys
from PySide.QtCore import *
from PySide.QtGui import *

width = 640
height = 480
brushPath = 'ball.png'


class ImageViewScene(QGraphicsScene):

    """ メインビューと関連付けられる Scene """

    def __init__(self, *argv, **keywords):
        super(ImageViewScene, self).__init__(*argv, **keywords)

        self.buttonFlag = False
        self.pixmap = QPixmap(width, height)
        self.pixmap.fill()
        self.brushImage = QPixmap(brushPath)

        # Scene に Item を追加
        self.imgItem = QGraphicsPixmapItem(self.pixmap)
        self.addItem(self.imgItem)

    def mouseDoubleClickEvent(self, event):
        pass

    def mousePressEvent(self, event):
        """ マウスボタンが押された際の処理 """
        if event.button() == Qt.LeftButton:
            self.buttonFlag = True
            self.drawing(event)
        elif event.button() == Qt.RightButton:
            self.pixmap.fill()
            self.imgItem.setPixmap(self.pixmap)

    def mouseMoveEvent(self, event):
        """ マウスカーソル移動中の処理 """
        if self.buttonFlag:
            self.drawing(event)

    def mouseReleaseEvent(self, event):
        """ マウスボタンが離されたときの処理 """
        if event.button() == Qt.LeftButton:
            self.buttonFlag = False

    def drawing(self, event):
        """ ブラシで描画 """
        x = event.scenePos().x()
        y = event.scenePos().y()
        x -= self.brushImage.width() / 2
        y -= self.brushImage.height() / 2
        qp = QPainter()
        qp.begin(self.pixmap)
        qp.drawPixmap(x, y, self.brushImage)
        qp.end()
        del qp

        # 描画更新する方法が分からない…
        # 仕方なく、pixmap を再設定してるけど…これでいいの?
        self.imgItem.setPixmap(self.pixmap)
        # self.imgItem.update()
        # self.update()


class ImageViewer(QGraphicsView):

    """ メインとなるビュー """

    def __init__(self):
        super(ImageViewer, self).__init__()

        self.setCacheMode(QGraphicsView.CacheBackground)
        self.setRenderHints(QPainter.Antialiasing |
                            QPainter.SmoothPixmapTransform |
                            QPainter.TextAntialiasing
                            )

        scene = ImageViewScene(self)
        self.setScene(scene)
        scene.setSceneRect(QRectF(self.rect()))

    def resizeEvent(self, event):
        """ ビューをリサイズ時にシーンの矩形を更新 """
        super(ImageViewer, self).resizeEvent(event)
        self.scene().setSceneRect(QRectF(self.rect()))

if __name__ == '__main__':
    app = QApplication(sys.argv)
    viewer = ImageViewer()
    viewer.show()
    sys.exit(app.exec_())

drawing_pyside_4_ss.gif

これで一応できた、のかな。

Qtには、ビットマップデータ相当として使える QPixmap てのがあるわけだけど。その QPixmap に対しては、QPainter を使って何か描き込むことができるわけで。

しかし、その QPixmap を渡して生成した QGraphicsPixmapItem の見た目を更新する方法がどうにも分からず。

結局、生成時に作った QPixmap を更新するたびに、QGraphicsPixmapItem の setPixmap() で設定し直してみたら、見た目も更新されるようになったけど…。果たしてコレでいいのだろうか…?

もしかして、QGraphicsPixmapItem が持ってる QPixmap は、QGraphicsPixmapItem の生成時、あるいは setPixmap() を呼んだ時に渡された QPixmap の内容を丸々コピーして持ってたりするのだろうかと。仮にそうであれば、生成時に渡した QPixmap を後から更新したところで、見た目も即座に更新されるわけでは無い、てのも分かる気もする。が、実際はどういう仕組みになっているのやら。

それと、どうせ QGraphicsPixmapItem が QPixmap を持っているなら、その QPixmap に直接描き込んでしまえばいいのではないか、とも思ったのだけど。試してみたところ、Pythonスクリプトが強制終了してしまって。となると…。 何にせよ、よく分かりません。

よく分からないと言えば…。QGraphicsView を使うとスクロールバーがなんだか中途半端な長さで出てくるのだけど、コレって何をどうやって設定したり使用したりするのだろう…。今後の課題。

以上です。

過去ログ表示

Prev - 2016/10 - Next
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project