--- Title: ベクタパス作成ツール 2 Author: yamasyuh68 Web: https://mimemo.io/m/BV8YKG0g834ry91 --- # オブジェクトベースに書き直し 190718 - 日中調べたことを家で実験、概ね思ったとおりなので、Qtのパスオブジェクトを直接操作する方向で進めることが出来そう - 保存も出来たので今後幅が広がると思う **今更だけどQtは凄いです** ## パスオブジェクトのエレメント - パスのエレメントのメンバーは type,x,y の三つだけ、これを出力した結果が以下で、前回の矢印のパスのデータです - タイプの種類は次の通り QPainterPath.MoveToElement 0 QPainterPath.LineToElement 1 QPainterPath.CurveToElement 2 QPainterPath.CurveToDataElement 3 - 座標をポイント p とコントロールポイント cp に分けたとして、ベジェ描画のメソッドでいうと、cubicTo( cp , cp , p ) になるが、このタイプは cubicTo( 2 , 3 , 3 ) ということになる - 予想外、( 2 , 2 , 3 ) とすべきだと思うんだが?? 最初はバグかなとも思ったが多分こういう方法が合理的なんだろう、いずれ理由がわかるかもしれない format: 0 x: 251.0 y: 45.0 <--- format: 2 x: 288.0 y: 118.0 format: 3 x: 341.0 y: 191.0 format: 3 x: 356.0 y: 233.0 <--- format: 2 x: 322.0 y: 209.0 format: 3 x: 301.0 y: 200.0 format: 3 x: 281.0 y: 193.0 <--- format: 2 x: 279.0 y: 263.0 format: 3 x: 241.0 y: 432.0 format: 3 x: 173.0 y: 488.0 <--- format: 2 x: 214.0 y: 416.0 format: 3 x: 226.0 y: 239.0 format: 3 x: 221.0 y: 193.0 <--- format: 2 x: 198.0 y: 199.0 format: 3 x: 179.0 y: 207.0 format: 3 x: 145.0 y: 224.0 <--- format: 2 x: 179.0 y: 186.0 format: 3 x: 223.0 y: 125.0 format: 3 x: 251.0 y: 45.0 - マウスでポイントをグリグリするとして、ポイントが p なのか cp なのかを区別することは重要だが、type からは判断できないことになる まあ規則的に並んでいるので判断は出来るんだけど、少し悩ましい ## データの保存・読み込み ``` def pathsave(self): fname=os.path.join(os.path.dirname(__file__) , 'qtsave') f = QFile(fname) f.open( QIODevice.WriteOnly ) ds = QDataStream(f) ds.__lshift__(self.path) f.close() def pathload(self): self.path=mypath(QPointF(0,0)) fname=os.path.join(os.path.dirname(__file__) , 'qtsave') f = QFile(fname) f.open( QIODevice.ReadOnly) ds = QDataStream(f) ds.__rshift__(self.path) f.close() self.path.makepointrect() self.update() ``` - ここ情報が少なかったけど何とか出来た - 公式ドキュメントでもC++の例しか記載が無い わからなかったのはストリームを作った後の読み書き ++だとシフト演算子 >> << で簡単にできるが、pythonにはそんなものない QDataStreamのドキュメントを見ると謎のSpecial Methodsで __lshift__がデータタイプ毎に延々と続いてる - **しばし悩んだが、わかった(・∀・)ノ** lshift は left shift 、左演算子のことだ、 >> ね - 次の課題としては複数のデータを保存する方法 ストリームが開いている間はいくらでも書き込めると思うので、どんどん書き込めば良いのかもしれないが、読み込むときに綺麗に分けて読めるんだろうか?? ## パスのサブクラス化 - これもうまくいってます パス全体の包含判定はメソッドが用意されているが、ポイントを選択するためにはポイントとマウス位置のヒット判定も必要 これは外からではなくてパスオブジェクトにさせた - contains をオーバーロードするのは怖いので contains_m というメソッドを用意して、そこで全体の包含判定とポイントの包含判定もさせてみた - ポイントの描画もパスオブジェクトから rect のリストをもらうように、メソッドを用意した - **クラス化した場合にどこまでそのクラスにやらせるべきか**は少し悩ましいが、逆にそこを考えることがプログラミングの面白さでもあるよなあ ## 閉じたパスについて - Qt でパスを閉じるメソッドがあるが、この機能はドキュメントにもあるとおりで、現在の終点と始点を直線で単純に結ぶだけだった - その意味は、①最後の線はベジェで無くなる②改めて始点を動かすとパスは開く - これでは使い物なら無いので独自に実装しよう( ´∀`) --- --> [PyQt でベクターオブジェクト作成ツールを作る #](https://mimemo.io/m/3Rx1XoR367le95E)