--- Title: PyQt でベジェ曲線を描画してマウスでグリグリする Author: yamasyuh68 Web: https://mimemo.io/m/grd5OG2YE54X2zM --- 190701 - Qtのパス操作で、path.cubicTo を使えばベジェが書けるのは知ってたけど、自分で数字を与えて希望通りの曲線になるはずも無く、現実には使えてなかった - ふとマウスでグリグリするアイデアを思いついたので早速試してみたら意外と簡単にできたので公開してみます こんな感じ、各ポイントをマウスで自由に移動できます https://live.staticflickr.com/65535/48179115881_a41a1d2f6e_z.jpg - コードです 環境はPython 3.72 と PyQt 5.12です ``` import sys from PyQt5.QtWidgets import QApplication, QWidget from PyQt5.QtCore import QPointF ,QRectF ,Qt from PyQt5.QtGui import QPainterPath ,QPainter ,QPen class App(QWidget): def __init__(self): super().__init__() self.setWindowTitle('hogetta') self.setGeometry( 500, 50 , 500 , 500 ) self.setMouseTracking (True) # <----------------***** self.plist=[] self.plist.append( QPointF(10,250) ) # start point self.plist.append( QPointF(100,100) ) # self.plist.append( QPointF(300,200) ) # self.plist.append( QPointF(490,250) ) # self.a = QPointF(4,4) # Tolerance in detecting point self.pselected = -1 # selectedpoint self.pmove = 0 # move flag self.show() def mouseMoveEvent(self ,e): if self.pmove : # Dorag ing self.plist[self.pselected] = e.pos() self.update() else: # non Dorag ing self.pselected = -1 rc = QRectF ( e.pos() - self.a , e.pos() + self.a ) for i, l in enumerate( self.plist ) : if rc.contains( l ) : self.pselected = i # self.setWindowTitle('HIT {}'.format(str(i))) self.update() break def mousePressEvent(self ,e): if self.pselected != -1 : self.pmove = True def mouseReleaseEvent(self ,e): self.pmove = False self.pselected = -1 def paintEvent (self,e): # 与えられたパラメータでパスを設定した後でパスをドローする path = QPainterPath( self.plist[0] ) path.cubicTo( self.plist[1] , self.plist[2] , self.plist[3] ) painter= QPainter() painter.begin(self) painter.setPen( QPen( Qt.black , 2, style=Qt.SolidLine ) ) painter.drawPath(path) painter.setPen( QPen( Qt.red , 2, style=Qt.DotLine ) ) painter.drawLine( self.plist[0] , self.plist[1] ) # sub painter.drawLine( self.plist[2] , self.plist[3] ) # sub if self.pselected != -1: painter.drawRect( QRectF(QPointF(self.plist[self.pselected]-self.a) , QPointF(self.plist[self.pselected]+self.a) )) painter.end() if __name__ == "__main__": app = QApplication(sys.argv) ex = App() sys.exit(app.exec_()) ``` ## 解説的なこと - ウイジェットを一つ作って(500-500)そこに直接描画してます - 最初のキューブは値をリストで与えてますが、端点は四つ、これをマウスでグリグリ - 端点の上にマウスを持って行けば■が表示されるようにして、その状態でドラッグすれば移動できます - とりあえずの実験です このキューブをつなげて複数にしていけば普通にベクターグラフィックの世界に入れると思います ## 参考 - 一から学ぶベジェ曲線 https://postd.cc/bezier-curves/ このサイト素晴らしい、わかりやすい、動くページ素晴らしいですね - ペイントの基本 https://qiita.com/kenasman/items/87c12f3a8b63f5948153 ここはQtのドキュメントの邦訳 いきなり読んでもわけわかんないけど振り返って読むとああそういうことだったんだなあと納得できたりします でもQtやるんなら英語ですが公式ドキュメントを読むようにした方が良いと思う、頑張って ---- → [戻る](https://mimemo.io/m/QORbW4qkvOoda0N) --- --> [PyQt でベクターオブジェクト作成ツールを作る #](https://mimemo.io/m/3Rx1XoR367le95E)