--- Title: 画像にパスを加えるツール 2 Author: yamasyuh68 Web: https://mimemo.io/m/BV8YKG0g3k4ry91 --- 190724 # パスファイルのビューア https://live.staticflickr.com/65535/48364789566_b5abd605e0.jpg - 画像にパスを追加するプログラム、作ったパスを読み込むときにサムネイルが必要なので作ってみた。矢印のパスを四つコピーして読み込ませてみた ``` import sys , os,glob from PyQt5.QtWidgets import (QApplication, QGraphicsItem, QGraphicsScene, QGraphicsView, QGraphicsDropShadowEffect ,QGraphicsPathItem ) from PyQt5.QtGui import QPixmap , QColor , QPainterPath ,QPen,QBrush from PyQt5.QtCore import Qt,QSizeF ,QPoint,QPointF ,QDataStream,QIODevice,QDataStream,QFile class PathView(QGraphicsView): def __init__(self, parent=None): super( PathView, self).__init__(parent) self.setGeometry(500,100,300,400) self.setScene(QGraphicsScene(self)) self.item=[] # sceneItem fname=os.path.join(os.path.dirname(__file__) , '*.qpath') for l in glob.iglob(fname , recursive=True) : f = QFile(l) f.open( QIODevice.ReadOnly) ds = QDataStream(f) path=QPainterPath() ds.__rshift__(path) f.close() self.item.append( [self.scene().addPath( path,brush = QBrush(Qt.red)) , l ] ) size=(80,80) ratio=0 ii=0 for i,l in enumerate( self.item ) : rect= l[0].boundingRect () ratio = min( size[0] / rect.width() , size[1] / rect.height() ) l[0].setScale( ratio ) ii = int(i / 3) # 横3つまで、ii は行数になる l[0].setPos( (i%3)*size[0] , ii*size[1] ) l[0].setFlag(QGraphicsItem.ItemIsSelectable,1) self.scene().selectionChanged.connect(self.selectionChanged) self.selected=None def selectionChanged(self): p=self.scene().selectedItems() if len(p) >= 1 : p=p[0] for l in self.item : if p==l[0] : self.setWindowTitle(l[1]) app = QApplication(sys.argv) window = PathView() window.show() sys.exit(app.exec_()) ``` - 本体がベース、viewにsceneを設定して、そこに、特定フォルダにあるパスファイルを全て読み込んでaddpathして、縮小表示している。 画像を見てクリックしたらそのパスファイルのフルパスを取得してタイトルに表示する - 基本は出来たので、このクラスを、読み込むときのダイアログとして使うか、オーサリングソフトみたいに使えるパーツとして常時表示させておくか、そこら辺は設計の問題になりますね # Transform 実験できた - QtのGraphicsItemViewは、デフォルトでスケーリングはできるが、縦横リンクしていて、縦だけ、横だけというメソッドは無い。画像はあるんだけどね。調べたらQTransformを使うことになるようだったので実験してみたら簡単だった - QTransformは複雑な変換が出来るようだけど、用途を限定すれば簡単だ - しかし、キーボード対応はやはり使いづらい。マウスでグリグリが基本ですよね。そのためにはBoundingRectを表示してマウスカーソルも変化させて、という事になると思うんだけど。 - 何らかのメソッドが用意されてるんだろうか?? 自力で実装しろと言われればするんだが、あとでメソッドがあった、というパターンは過去にもあったのでもう少し調べてみるか・・・ ``` def keyPressEvent(self, event): if (event.modifiers() & Qt.ControlModifier): # ctrl if (event.key() == Qt.Key_Up): self.y += 0.1 elif (event.key() == Qt.Key_Down): self.y -= 0.1 elif (event.key() == Qt.Key_Q): self.setPath( self.original ) self.y=1 return elif (event.key() == Qt.Key_Right): self.x += 0.1 elif (event.key() == Qt.Key_Left): self.x -= 0.1 qt = QTransform() qt.scale( self.x, self.y ) self.setPath( qt.map( self.original ) ) return ``` ---- 190729 # scene の保存 - 結構難しくてここ数日やってるがまだまだだ - Qpixmap をつくってrenderしてやれば良いんだが、領域の指定が難しい - 現状はスクロールバーが出ている状態ではうまく書き出せてる しかし逆にviewの方が大きい時はうまくいかない secene、viewport、メインのpictureの位置、ここら辺の座標をしっかり把握しておかないといけないが難しいんですよ - 今のところ解決策がわからない。viewを小さくしてやれば書き出せるので意欲が今ひとつってのもありますね --- 190730 # マウスで変形させる ## 基本となるrectで実験 - 単純なrectでGraphicPathItemの派生クラスを作ってマウスでtransform出来るか実験中 - うまくいけば実際に使うパスは常にこのrectの子供としてシンクロさせることでtransformを実現させたい - マウスで横だけ伸ばすところまでは出来た - rect上にコントロールポイントを描画してそこの包含判定で縦や横の切替をしようと思ったが、描画したコントロールポイントはtransformにうまく連動してくれない 回転には連動するけど横伸長には連動してくれない┐('д')┌ - 組み込みのscale,rotateには連動するけど直接transformしたらダメなのか?? - もう一息のような気がするんだけど・・・・ キーで変形するのは簡単だなあ でもマウスでグリグリが操作としてはやはり基本だと思った ## hover - hoverMoveEvent は機能してなかったけど来るようになったので、カーソル形状も自由に変えれるようになった SetAcceptするだけ。わかってたんだが、acceptしてた。よくある勘違い(^^)/ - widgetならmousetrackingでmousemoveが来るようになるけど、GraphicItemは違うんだな それでhoverMoveEventの仕組みがあるんだと思う mouseMoveはドラッグ時にしか機能しない ## 中心の設定 - パスの中心の設定は大事だ 作ったパスは0を原点には作ってないけど、boundingRectは0ベースなのでよくわかってなかった 中心設定はあくまで元のパスの原点ベース パスを部品として使うなら一旦原点に移動してから保存した方が良いって事ですよね --- ---> [PyQt で画像にパスを加えるツールを作る #](https://mimemo.io/m/JkWVal6ZmJlBEqd)