PyQt5之QGraphics 008 QGraphicsItem四连杆机构动画

首先看一下效果:

机械相关专业的同学,在学习机械原理这门课的时候一定做过四连杆方面的运动分析,

以下,用PyQt做四连杆的动画。先不考虑有死点等特殊机构的情况。

其中,l4杆是固定的,其它三根是活动的。

定义B点坐标 bPoint = QPointF(bx,  by)

定义C点坐标 cPoint = QPointF(cx,  cy)

各杆的长度为 l1(曲杆), l2(连杆) , l3(摇杆), l4(机架)

定义A点坐标 aPoint = QPointF(0, 0),那么D点为 dPoint = QPointF(l4, 0)

只要用到余弦公式:

A*A + B*B - 2*A*B*cos(c) = C*C

代码如下:

"""
PyQt5之QGraphics 007 QGraphicsItem四连杆机构动画
2020-03-25
By Linyoubiao
"""

from PyQt5.QtWidgets import (QApplication, QGraphicsView, QGraphicsScene, QGraphicsItem)
from PyQt5.QtCore import (QPoint, QPointF, QRect, QRectF, QLine, QLineF, QTimer, Qt)
from PyQt5.QtGui import (QPainterPath, QBrush, QPen, QColor)
import math
import timer


class Line(QGraphicsItem):
    def __init__(self):
        super(Line, self).__init__()
        # 曲柄
        self.L1 = 16
        # 连杆
        self.L2 = 74
        # 剪刀杆
        self.L3 = 84
        # 支架
        self.L4 = 62
        # 曲柄的角速度
        self.angular_speed = math.pi/2
        # 每一次动画转动的角度
        self.angle_animation = math.pi/30
        # 夹角
        self.angle_1 = .0
        self.angle_2 = .0
        self.angle_3 = .0
        self.angle_BDA = .0
        self.angle_CBD = .0
        self.angle_CDB = .0
        # BD两点的距离
        self.e = .0

        # B点坐标
        self.bx = .0
        self.by = .0
        # C点坐标
        self.cx = .0
        self.cy = .0
        # B点坐标
        self.dx = .0
        self.dy = .0

        self.timer = QTimer()
        self.timer.timeout.connect(self.timerEvent)
        self.timer.start(30)

    def boundingRect(self):
        rect = QRectF(QPointF(-50, -50), QPointF(100, 100))
        return rect

    def timerEvent(self):
        # 要增加,以更新painter
        self.prepareGeometryChange()

        self.angle_1 -= self.angle_animation
        self.e = math.sqrt(self.L1**2 + self.L4**2 - 2*self.L1*self.L4*math.cos(self.angle_1))
        self.angle_BDA = math.acos((self.e**2 + self.L4**2 - self.L1**2)/(2*self.L4*self.e))
        self.angle_CBD = math.acos((self.e**2 + self.L2**2 - self.L3**2)/(2*self.L2*self.e))
        self.angle_CDB = math.acos((self.e**2 + self.L3**2 - self.L2**2)/(2*self.L3*self.e))

        self.bx = self.L1 * math.cos(self.angle_1)
        self.by = self.L1 * math.sin(self.angle_1)

        if self.by > 0:
            self.angle_2 = self.angle_CBD - self.angle_BDA
        else:
            self.angle_2 = self.angle_CBD + self.angle_BDA

        self.angle_3 = math.pi - (self.angle_CDB + self.angle_BDA)

        self.cx = self.bx + self.L2 * math.cos(self.angle_2)
        self.cy = self.by + self.L2 * math.sin(self.angle_2)

    def paint(self, painter, option, widget):
        painter.setPen(QPen(QBrush(Qt.black), 5))
        painter.drawLine(QLineF(QPointF(0, 0), QPointF(self.L4, 0)))

        painter.setPen(QPen(QBrush(Qt.red), 3))
        painter.drawLine(QLineF(QPointF(0, 0), QPointF(self.bx, self.by)))
        painter.setPen(QPen(QBrush(Qt.green), 3))
        painter.drawLine(QLineF(QPointF(self.bx, self.by), QPointF(self.cx, self.cy)))
        painter.setPen(QPen(QBrush(Qt.blue), 3))
        painter.drawLine(QLineF(QPointF(self.cx, self.cy), QPointF(self.L4, 0)))

        painter.setPen(QPen(QBrush(Qt.darkGray), 1))
        painter.drawEllipse(QPointF(0, 0), self.L1, self.L1)
        painter.drawEllipse(QPointF(self.L4, 0), self.L3, self.L3)


class Scene(QGraphicsScene):
    def __init__(self):
        super(Scene, self).__init__()
        item = Line()
        self.addItem(item)


class View(QGraphicsView):
    def __init__(self):
        super(View, self).__init__()
        scene = Scene()
        self.setScene(scene)


if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)

    view = View()
    view.setWindowTitle("四连杆")
    view.show()

    sys.exit(app.exec_())


 

PyQt5中,`QGraphicsItem`是一个基础类,它是所有图形元素如形状、图像、文本等在`QGraphicsScene`中绘制的核心组件。如果你想要创建自定义图形元素,可以继承`QGraphicsItem`。 继承`QGraphicsItem`的过程通常包括以下几个步骤: 1. **继承**:首先创建一个新的类,例如`MyCustomShape`,它会继承自`QGraphicsItem`。你可以添加额外的数据成员(属性)和方法来满足你的需求。 ```python from PyQt5.QtWidgets import QGraphicsItem class MyCustomShape(QGraphicsItem): def __init__(self, parent=None): super(MyCustomShape, self).__init__(parent) # 添加初始化代码... ``` 2. **实现必要方法**:`QGraphicsItem`有一些核心方法需要重写,如`boundingRect()`(返回物品的边界矩形)、`paint()`(用于渲染)以及鼠标事件处理等。例如,你可以重写`paint()`来定义你的图形如何绘制: ```python def paint(self, painter, option, widget=None): # 在这里定义绘画逻辑... ``` 3. **重写生命周期方法**:如果需要控制图形的行为,可能会重写一些生命周期方法,比如`mousePressEvent()` 或 `hoverEnterEvent()` 等。 4. **显示实例**:在`QGraphicsScene`中添加你的自定义`QGraphicsItem`实例: ```python scene = QGraphicsScene() custom_shape = MyCustomShape() scene.addItem(custom_shape) ``` 通过这种方式,你可以在不改变原有`QGraphicsItem`功能的基础上,定制出具有独特特性的新图形元素。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值