实现方式:依托QLinearGradient 和QPainter进行绘制图层。
# coding=utf-8
# python3
"""
@FileName:自定义Label,近似信号光点传输效果.py
@Author: XiaoFang
@CreateFileTime: 2024/7/10 7:10
@Description:
"""
import sys
from PyQt5.QtWidgets import QApplication, QLabel, QVBoxLayout, QWidget, QPushButton
from PyQt5.QtCore import QTimer, Qt, QPoint
from PyQt5.QtGui import QPixmap, QPainter, QBrush, QColor, QPolygon, QLinearGradient
class ArrowLabel(QLabel):
def __init__(self, parent=None):
super().__init__()
self.coverage = 0.1
self.point = []
self.left = 1
self.right = 0
self.step_time = 0.05
self.timer = QTimer(self)
self.timer.timeout.connect(self.update_coverage)
def set_point_direction(self, point, _time, left_start=1):
self.point = point
self.step_time = _time
self.change_direction(left_start)
def change_direction(self, left_start):
if left_start == 1:
self.left = 0
self.right = 1
else:
self.left = 1
self.right = 0
self.update_arrow()
def pause_timer(self):
self.timer.stop()
def resume_timer(self, _time):
if _time == 0:
return
if self.timer.isActive():
self.timer.stop()
self.timer.start(_time)
def update_coverage(self):
self.coverage += self.step_time
if self.coverage > 1:
self.coverage = 0.01
# self.timer.stop()
# self.clear_arrow()
else:
self.update_arrow()
def update_arrow(self):
pixmap = QPixmap(200, 55)
pixmap.fill(Qt.transparent)
painter = QPainter(pixmap)
coverage_before = self.coverage - 0.05 if self.coverage - 0.05 > 0 else 0
coverage_after = self.coverage + 0.05 if self.coverage + 0.05 < 1 else 1
gradient = QLinearGradient(255*self.left, 0, 255*self.right, 0) # 更改方向
gradient.setColorAt(0, QColor(200, 200, 200, 255)) # 全灰
gradient.setColorAt(coverage_before, QColor(200, 200, 200, 255)) # 灰
gradient.setColorAt(self.coverage, QColor(0, 255, 0, 255)) # 绿色
gradient.setColorAt(coverage_after, QColor(200, 200, 200, 255)) # 灰
brush = QBrush(gradient)
painter.setBrush(brush)
painter.setPen(Qt.NoPen)
points = QPolygon(self.point)
painter.drawPolygon(points)
painter.end()
self.setPixmap(pixmap)
def clear_arrow(self):
pixmap = QPixmap(200, 55)
pixmap.fill(Qt.transparent)
painter = QPainter(pixmap)
gradient = QLinearGradient(255*self.left, 0, 255*self.right, 0)
gradient.setColorAt(0, QColor(170, 170, 170, 255))
gradient.setColorAt(1, QColor(170, 170, 170, 255))
brush = QBrush(gradient)
painter.setBrush(brush)
painter.setPen(Qt.NoPen)
points = QPolygon(self.point)
painter.drawPolygon(points)
painter.end()
self.setPixmap(pixmap)
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.setGeometry(100, 100, 300, 300)
layout = QVBoxLayout()
weight = QWidget()
weight.setFixedSize(300, 200)
layout.addWidget(weight)
layout.setContentsMargins(0, 0, 0, 0)
layout2 = QVBoxLayout(weight)
layout2.setContentsMargins(0, 0, 0, 0)
layout2.setSpacing(0)
self.arrow_label = ArrowLabel()
layout2.addWidget(self.arrow_label)
self.setLayout(layout)
self.arrow_label.set_point_direction([
QPoint(50, 50),
QPoint(250, 50),
QPoint(250, 100),
QPoint(50, 100),
QPoint(50, 50),
], _time=0.01, left_start=0)
self.button = QPushButton('开始', self)
self.button.clicked.connect(self.activate_timer)
layout2.addWidget(self.button)
self.button_direction = QPushButton('向右', self)
self.button_direction.clicked.connect(self.direction_change)
layout2.addWidget(self.button_direction)
def activate_timer(self):
if self.button.text() == '开始':
self.button.setText('暂停')
self.arrow_label.resume_timer(10)
else:
self.button.setText('开始')
self.arrow_label.pause_timer()
def direction_change(self):
if self.button_direction.text() == '向左':
self.button_direction.setText('向右')
self.arrow_label.change_direction(left_start=0)
else:
self.button_direction.setText('向左')
self.arrow_label.change_direction(left_start=1)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
运行效果:
自定义Label,近似信号光点传输效果