--- Title: 画像にパスを加えるツール Author: yamasyuh68 Web: https://mimemo.io/m/ydN6woxKN8Gp7qE --- 190721 # 画像との結合 https://live.staticflickr.com/65535/48337267662_8d8df672d9_b.jpg ``` import sys , os from PyQt5.QtWidgets import (QApplication, QGraphicsItem, QGraphicsScene, QGraphicsView, QGraphicsDropShadowEffect ,QGraphicsPathItem ) from PyQt5.QtSvg import QGraphicsSvgItem from PyQt5.QtGui import QPixmap , QColor , QPainterPath ,QPen from PyQt5.QtCore import Qt,QSizeF ,QPoint,QPointF ,Qt,QDataStream,QIODevice,QDataStream,QFile class pathitem(QGraphicsPathItem): def __init__(self,filename): super().__init__(filename) self.setCursor(Qt.OpenHandCursor) self.setAcceptedMouseButtons(Qt.LeftButton) self.setFlag(QGraphicsItem.ItemIsSelectable,1) self.setFlag(QGraphicsItem.ItemIsMovable,1) self.setGraphicsEffect(QGraphicsDropShadowEffect()) self.setTransformOriginPoint(self.boundingRect().width()/2, self.boundingRect().height()/2) self.angle=0 self.scale=1.0 self.distance=5.0 self.radius=1.0 def mousePressEvent(self, event): self.setCursor(Qt.ClosedHandCursor) super().mousePressEvent(event) def mouseReleaseEvent(self, event): self.setCursor(Qt.OpenHandCursor) super().mouseReleaseEvent(event) def mouseMoveEvent(self, event): super().mouseMoveEvent(event) def keyPressEvent(self, event): if (event.modifiers() & Qt.ShiftModifier): # shift if (event.key() == Qt.Key_Up): self.distance += 0.5 elif (event.key() == Qt.Key_Down): self.distance -= 0.5 elif (event.key() == Qt.Key_Right): self.radius += 0.5 elif (event.key() == Qt.Key_Left): self.radius -= 0.5 self.graphicsEffect().setOffset(self.distance) self.graphicsEffect().setBlurRadius(self.distance) return if (event.key() == Qt.Key_Right): self.angle += 1 elif (event.key() == Qt.Key_Left): self.angle -= 1 elif (event.key() == Qt.Key_Up): self.scale += 0.1 elif (event.key() == Qt.Key_Down): self.scale -= 0.1 # elif (event.key() == Qt.Key_Escape): # return self.setScale(self.scale) self.setRotation(self.angle) def paint(self,painter,option,n): painter.setPen( QPen( Qt.red , 2, style=Qt.SolidLine ) ) painter.setBrush( Qt.red ) painter.drawPath(self.path()) class SvgView(QGraphicsView): def __init__(self, parent=None): super(SvgView, self).__init__(parent) self.pix = QPixmap(r'e:\Programs\python\qt\svg\cat.png') fname=os.path.join(os.path.dirname(__file__) , 'qtpath.qtdata') f = QFile(fname) f.open( QIODevice.ReadOnly) ds = QDataStream(f) path=QPainterPath() ds.__rshift__(path) f.close() self.path=pathitem(path) self.setScene(QGraphicsScene(self)) self.scene().addPixmap(self.pix) self.scene().addItem(self.path self.scene().selectionChanged.connect(self.selectionChanged) self.selected=None def selectionChanged(self): if self.selected : self.selected.ungrabKeyboard() p=self.scene().selectedItems() if len(p) >= 1 : p=p[0] p.grabKeyboard() self.selected=p app = QApplication(sys.argv) window = SvgView() window.show() sys.exit(app.exec_()) ``` - 前に書いたプログラムの使い回し QGraphicsPathItemの派生クラスはsvg用のクラスの親をpathに変えただけで一切変更していないが、完璧に動作してます - paintメッソドを新たに実装した 無くても描画されますが、黒ペンでブラシ無しだったので、適当に設定した ここを変えたら自由な色で塗れる、グラデもアリだな、しないけど - 影のイフェクトも完璧です、Qtすごいね、しつこいけど - 作った画像の保存ルーチンは書いてない( ´∀`) widget の grab なら簡単だと思うが、書き出し用のメソッドがあるのかな? - このプログラムは自作のパスを使い回しできるので、パスを作ってパーツとして選べるようにしておきたい ウインドウ中に置くか、ダイアログで選択させるかは設計上の問題ですね パスの線とブラシの色選択画面はウインドウ中の方が良いのかな イフェクトの操作もできた方が良いか - これって状態の保存は出来るのかしら?? できたら簡単な画像加工ソフトになるね ---- 190722 - 画像保存出来た これでQImageに書き出せってドキュメントには書いてある しかしViewにすべきかSceneにすべきか? 両方に同じメソッドが用意されていて引数も全く同じだ メインがviewで作ったからviewでいいか >QGraphicsView.render (self, QPainter painter, QRectF target = QRectF(), QRect source = QRect(), Qt.AspectRatioMode mode = Qt.KeepAspectRatio) >QGraphicsScene.render (self, QPainter painter, QRectF target = QRectF(), QRectF source = QRectF(), Qt.AspectRatioMode mode = Qt.KeepAspectRatio) - **paint周りが今ひとつわからない** 今回もengineがないエラーになった painterのbegin()もどういう場合に必須なのかわからない 自分で書く場合とシステムから呼ばれる場合で違うのだろうか?? 勉強が必要だな ( ̄― ̄?) - あとrectの指定がよくわからん┐('д')┌ --- ---> [PyQt で画像にパスを加えるツールを作る #](https://mimemo.io/m/JkWVal6ZmJlBEqd)