大家好!今天我们将一起来探讨一下如何使用PyQt,这是一个强大的Python库,来绘制一个传统的太极图。这个图案代表着古老的阴阳哲学,而我们的代码将以大白话的方式向你揭示它的奥秘。
PyQt:是什么鬼?
首先,我们得了解一下PyQt。它是一个Python库,让你能够创建漂亮、跨平台的桌面应用程序。要记住的一点是,它基于Qt,这是一个功能强大的图形用户界面框架。
代码的开胃菜
好的,现在让我们来看看代码的一些小细节。
class TaiChiWidget(QWidget):
def __init__(self):
super().__init__()
self.setGeometry(100, 100, 200, 200)
self.setWindowTitle('Tai Chi with Bezier Curve')
这里我们定义了一个名为 TaiChiWidget
的类,继承自 QWidget
。在这个类的构造函数中,我们设置了窗口的大小和标题。
绘制鱼形,添阴阳
接下来的绘图操作是代码的精华。
def paintEvent(self, event):
painter = QPainter(self)
painter.rotate(30)
painter.setRenderHint(QPainter.Antialiasing)
path = QPainterPath()
# 绘制 左侧黑鱼
c = QPointF(50, 50)
rect = QRectF(0, 0, 100, 100)
path.moveTo(c)
path.arcTo(rect, 90.0, 180.0)
path.arcTo(QRectF(25, 50, 50, 50), -90, 180.0)
path.arcTo(QRectF(25, 0, 50, 50), -90, -180.0)
这段代码通过创建一个 QPainter
对象,实现了旋转、抗锯齿等效果。然后,通过 QPainterPath
对象,使用一系列的 arcTo
操作,巧妙地画出了太极图的左半部分——黑鱼的形状。
白色大圆圈和小鱼眼
# 绘制白色大圆圈
painter.setBrush(Qt.white)
painter.setPen(Qt.white)
painter.drawEllipse(QPointF(50, 50), 50, 50)
painter.fillPath(path, QBrush(Qt.black))
# 绘制两个小圆圈(鱼眼)
painter.setPen(Qt.white)
painter.drawEllipse(QPointF(50, 75), 7, 7)
painter.setBrush(Qt.black)
painter.setPen(Qt.black)
painter.drawEllipse(QPointF(50, 25), 7, 7)
painter.setPen(QPen(Qt.black, 2))
这部分代码用于绘制太极图的右半部分,即白色的大圆圈和两个小黑白鱼眼。通过设置画刷和画笔的颜色,巧妙地营造出阴阳的对比。
完整代码
import sys
from PyQt5.QtGui import QPainter, QPainterPath, QBrush, QPen, QColor, QTransform
from PyQt5.QtCore import Qt, QPointF, QRectF
from rotate_widget import RotatedWidget
from PyQt5.QtWidgets import QApplication, QGraphicsView, QGraphicsScene, QGraphicsProxyWidget, QPushButton, QLabel, \
QVBoxLayout, QWidget
from PyQt5.QtCore import Qt
class TaiChiWidget(QWidget):
def __init__(self):
super().__init__()
self.setGeometry(100, 100, 200, 200)
self.setWindowTitle('Tai Chi with Bezier Curve')
def paintEvent(self, event):
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
path = QPainterPath()
# 绘制 左侧黑鱼
c = QPointF(50, 50)
rect = QRectF(0, 0, 100, 100)
path.moveTo(c)
path.arcTo(rect, 90.0, 180.0)
path.arcTo(QRectF(25, 50, 50, 50), -90, 180.0)
path.arcTo(QRectF(25, 0, 50, 50), -90, -180.0)
# 绘制白色大圆圈
painter.setBrush(Qt.white)
painter.setPen(Qt.white)
painter.drawEllipse(QPointF(50, 50), 50, 50)
painter.fillPath(path, QBrush(Qt.black))
# 绘制两个小圆圈(鱼眼)
painter.setPen(Qt.white)
painter.drawEllipse(QPointF(50, 75), 7, 7)
painter.setBrush(Qt.black)
painter.setPen(Qt.black)
painter.drawEllipse(QPointF(50, 25), 7, 7)
painter.setPen(QPen(Qt.black, 2))
def test():
app = QApplication(sys.argv)
tai_chi_widget = TaiChiWidget()
tai_chi_widget.show()
sys.exit(app.exec_())
if __name__ == '__main__':
test()
增加旋转功能
import sys
from PyQt5.QtGui import QPainter, QPainterPath, QBrush, QPen, QColor, QTransform
from PyQt5.QtCore import Qt, QPointF, QRectF
from rotate_widget import RotatedWidget
from PyQt5.QtWidgets import QApplication, QGraphicsView, QGraphicsScene, QGraphicsProxyWidget, QPushButton, QLabel, \
QVBoxLayout, QWidget
from PyQt5.QtCore import Qt
class RotatedWidget(QGraphicsView):
def __init__(self, content_widget, angle, parent=None):
super().__init__(parent)
self.angle = angle
scene = QGraphicsScene(self)
self.setScene(scene)
# 创建 QGraphicsProxyWidget
self.proxy_widget = QGraphicsProxyWidget()
self.proxy_widget.setWidget(content_widget)
self.proxy_widget.setTransformOriginPoint(content_widget.width() / 2, content_widget.height() / 2)
scene.addItem(self.proxy_widget)
self.rotate(self.angle)
self.startTimer(1000/60)
def timerEvent(self, a0):
self.angle -= 1
self.rotate(self.angle)
self.update()
def rotate(self, angle):
self.proxy_widget.setRotation(angle)
class TaiChiWidget2(QWidget):
def __init__(self):
super().__init__()
self.radius = 100
self.setGeometry(100, 100, 200, 200)
self.setStyleSheet("background-color: white;")
self.setWindowTitle('Tai Chi with Bezier Curve')
def paintEvent(self, event):
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
painter.setPen(QPen(Qt.black, 0.5))
path = QPainterPath()
# 绘制 左侧黑鱼
c = QPointF(self.radius, self.radius)
rect = QRectF(0, 0, self.radius * 2, self.radius * 2)
path.moveTo(c)
path.arcTo(rect, 90.0, 180.0)
path.arcTo(QRectF(self.radius / 2, self.radius, self.radius, self.radius), -90, 180.0)
path.arcTo(QRectF(self.radius / 2, 0, self.radius, self.radius), -90, -180.0)
# 绘制白色大圆圈
painter.setBrush(Qt.white)
painter.drawEllipse(QPointF(self.radius, self.radius), self.radius, self.radius)
painter.fillPath(path, QBrush(Qt.black))
# 绘制两个小圆圈(鱼眼)
painter.setPen(Qt.white)
painter.drawEllipse(QPointF(self.radius, self.radius * 3 / 2), self.radius * 0.15, self.radius * 0.15)
painter.setBrush(Qt.black)
painter.setPen(Qt.black)
painter.drawEllipse(QPointF(self.radius, self.radius / 2), self.radius * 0.15, self.radius * 0.15)
def test():
app = QApplication(sys.argv)
tai_chi_widget = TaiChiWidget2()
t = RotatedWidget(tai_chi_widget, 60)
t.show()
sys.exit(app.exec_())
if __name__ == '__main__':
test()