幾何学模様を作成する
まず、プッシュボタンUIで直線を回転させながら複製すると単純な放射状の幾何学模様が作れます。さらにスピンボックスUIで1つ目のコントロールポイントのY座標を移動してプッシュボタンUIを押すと、ちょっとした幾何学模様が作れます。それから2つのコントロールポイントのXY座標を移動できるようにすれば本格的な幾何学模様が作れます。
プッシュボタンUIを押して幾何学模様を描画
サンプルスクリプト「dlg_bezier2.py」に追加して、次のスクリプトを追記します。スピンボックスUIを操作するときはベジェ曲線1本だけを描画し、プッシュボタンUIを押したときに放射状にベジェ曲線を回転させて描画します(図5)。ベジェ曲線のコントロールポイントは第5回で解説した通り、直線を磁石で引っ張ったような座標です。
図4:放射状に幾何学模様を描く
・サンプルスクリプト「dlg_bezier3.py」
03 | from PyQt5.QtWidgets import QDialog, QHBoxLayout, QSpinBox, QLabel, QPushButton |
09 | def bezier(self,painter): |
12 | ctrl_y1 = self.sb_ctrl_y1.value() |
15 | path.cubicTo(ctrl_x1,ctrl_y1,ctrl_x2,ctrl_y2,200,0) |
16 | painter.drawPath(path) |
18 | def click_button(self): |
19 | self.img = self.draw_bezier(360) |
21 | self.doc.refreshProjection() |
25 | self.create_doc(800,800) |
26 | layout = QHBoxLayout() |
27 | self.button = QPushButton("幾何学模様の作成") |
28 | layout.addWidget(self.button) |
29 | self.button.clicked.connect(self.click_button) |
31 | self.label_ctrl_y1 = QLabel(" Ctrl Y1") |
32 | layout.addWidget(self.label_ctrl_y1) |
34 | self.sb_ctrl_y1 = QSpinBox() |
35 | self.sb_ctrl_y1.setMinimum(-2000) |
36 | self.sb_ctrl_y1.setMaximum(2000) |
37 | self.sb_ctrl_y1.setSingleStep(50) |
38 | self.sb_ctrl_y1.valueChanged.connect(self.click_sb) |
39 | layout.addWidget(self.sb_ctrl_y1) |
40 | self.setLayout(layout) |
【サンプルスクリプトの解説】
PyQt5モジュールのスピンボックスUIとラベルUIとプッシュボタンUIのウィジェットを読み込みます。
bezierメソッドでベジェ曲線の1つ目のコントロールポイントのY座標だけ移動を反映します。
「click_button」メソッドでプッシュボタンUIが押されたら360度の放射状に回転させたベジェ曲線を描きます。
createメソッドでプッシュボタンUIとスピンボックスUIを配置します。1つ目のコントロールポイントのY座標が変化したらclick_sbメソッドを呼び出すようにフックします。
ベジェ曲線の変形を仕上げる
サンプルスクリプト「dlg_bezier3.py」に追加して、次のスクリプトを追記します。ベジェ曲線の2つのコントロールポイントのXY座標も移動できるようにしました(図5)。これで完成です。つまり幾何学模様は1つの図形を規則的に繰り返しているだけなんですね。
図5:ベジェ曲線から幾何学模様を描く
・サンプルスクリプト「dlg_bezier4.py」
06 | def bezier(self,painter): |
08 | ctrl_x1 = self.sb_ctrl_x1.value() |
09 | ctrl_y1 = self.sb_ctrl_y1.value() |
10 | ctrl_x2 = self.sb_ctrl_x2.value() |
11 | ctrl_y2 = self.sb_ctrl_y2.value() |
12 | path.cubicTo(ctrl_x1,ctrl_y1,ctrl_x2,ctrl_y2,200,0) |
13 | painter.drawPath(path) |
17 | self.create_doc(800,800) |
18 | layout = QHBoxLayout() |
19 | self.button = QPushButton("幾何学模様の作成") |
20 | layout.addWidget(self.button) |
21 | self.button.clicked.connect(self.click_button) |
23 | self.label_x1 = QLabel(" Ctrl X1") |
24 | layout.addWidget(self.label_x1) |
26 | self.sb_ctrl_x1 = QSpinBox() |
27 | self.sb_ctrl_x1.setMinimum(-1000) |
28 | self.sb_ctrl_x1.setMaximum(1000) |
29 | self.sb_ctrl_x1.setSingleStep(25) |
30 | self.sb_ctrl_x1.setValue(50) |
31 | self.sb_ctrl_x1.valueChanged.connect(self.click_sb) |
32 | layout.addWidget(self.sb_ctrl_x1) |
34 | self.label_ctrl_y1 = QLabel(" Ctrl Y1") |
35 | layout.addWidget(self.label_ctrl_y1) |
37 | self.sb_ctrl_y1 = QSpinBox() |
38 | self.sb_ctrl_y1.setMinimum(-2000) |
39 | self.sb_ctrl_y1.setMaximum(2000) |
40 | self.sb_ctrl_y1.setSingleStep(50) |
41 | self.sb_ctrl_y1.valueChanged.connect(self.click_sb) |
42 | layout.addWidget(self.sb_ctrl_y1) |
44 | self.label_x2 = QLabel(" Ctrl X2") |
45 | layout.addWidget(self.label_x2) |
47 | self.sb_ctrl_x2 = QSpinBox() |
48 | self.sb_ctrl_x2.setMinimum(-1000) |
49 | self.sb_ctrl_x2.setMaximum(1000) |
50 | self.sb_ctrl_x2.setSingleStep(25) |
51 | self.sb_ctrl_x2.setValue(150) |
52 | self.sb_ctrl_x2.valueChanged.connect(self.click_sb) |
53 | layout.addWidget(self.sb_ctrl_x2) |
55 | self.label_ctrl_y2 = QLabel(" Ctrl Y2") |
56 | layout.addWidget(self.label_ctrl_y2) |
58 | self.sb_ctrl_y2 = QSpinBox() |
59 | self.sb_ctrl_y2.setMinimum(-2000) |
60 | self.sb_ctrl_y2.setMaximum(2000) |
61 | self.sb_ctrl_y2.setSingleStep(50) |
62 | self.sb_ctrl_y2.valueChanged.connect(self.click_sb) |
63 | layout.addWidget(self.sb_ctrl_y2) |
64 | self.setLayout(layout) |
【サンプルスクリプトの解説】
bezierメソッドで2つのコントロールポイントのXY座標の移動を反映します。
createメソッドで2つのコントロールポイントのXY座標のスピンボックスUIを配置し、click_sbメソッドにフックします。1つ目のコントロールポイントのスピンボックスUIがsb_ctrl_x1プロパティとsb_ctrl_y1プロパティで、2つ目のコントロールポイントのスピンボックスUIがsb_ctrl_x2プロパティとsb_ctrl_y2プロパティです。