PyQt でベジェ曲線を描画してマウスでグリグリする version 14
:追加された部分
:削除された部分
(差分が大きい場合、文字単位では表示しません)
PyQt でベジェ曲線を描画の実験してマウスでグリグリする
- 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)
self.pselected = -1 # selectedpoint
self.pmove = 0 # should move
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やるんなら英語ですが公式ドキュメントを読むようにした方が良いと思う、頑張って
-
Qtのパス操作で、path.cubicTo を使えばベジェが書けるのは知ってたけど、自分で数字を与えて希望通りの曲線になるはずも無く、現実には使えてなかった
-
ふとマウスでグリグリするアイデアを思いついたので早速試してみたら意外と簡単にできたので公開してみます
こんな感じ、各ポイントをマウスで自由に移動できます
-
コードです
環境は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)
self.pselected = -1 # selectedpoint
self.pmove = 0 # should move
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やるんなら英語ですが公式ドキュメントを読むようにした方が良いと思う、頑張って