您现在的位置是:网站首页 > 博客日记 >

PySide2音乐播放专辑图片旋转效果

作者:YXN-python 阅读量:19 发布日期:2024-11-05

import sys
from io import BytesIO

import requests
from PySide2.QtCore import Qt, QTimer, Signal
from PySide2.QtGui import QPainter, QPixmap, QPainterPath
from PySide2.QtWidgets import QApplication, QWidget, QHBoxLayout, QPushButton


class AlbumRotatingIcon(QWidget):
    album_clicked = Signal(str)

    def __init__(self, parent=None, bg_img_path='', album_img_path='', size=64, diff_size=20):
        super(AlbumRotatingIcon, self).__init__(parent)

        self.size = size
        self.diff_size = diff_size

        # 加载背景图片
        self.bg_img = QPixmap(bg_img_path).scaled(
            size, size, Qt.KeepAspectRatioByExpanding, Qt.SmoothTransformation
        )

        # 加载并处理前景图片
        self.album_img = self.prepare_album_image(album_img_path)

        self.angle = 0
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.rotateDisc)
        self.timer.start(50)  # 每50毫秒更新

        self.setMinimumSize(size, size)

        self.is_rotating = True  # 用于跟踪当前旋转状态

    def prepare_album_image(self, album_img_path):
        album_img = QPixmap(album_img_path)

        # 计算前景图片的最短边
        min_side = min(album_img.width(), album_img.height())

        # 使用裁剪区域定义一个正方形区域
        x_offset = (album_img.width() - min_side) // 2
        y_offset = (album_img.height() - min_side) // 2
        cropped_pixmap = album_img.copy(x_offset, y_offset, min_side, min_side)

        # 将裁剪后的正方形图像缩放来适应小圈(size-20)的大小
        return cropped_pixmap.scaled(
            self.size - self.diff_size, self.size - self.diff_size,
            Qt.KeepAspectRatioByExpanding, Qt.SmoothTransformation
        )

    # 更新图片
    def up_img(self, img):
        """
        支持三种方式
        1、网络图片地址 http://yixiuna.top/images/thumbnail/1726731481977697d044.jpg
        2、本地图片地址 logo.ico
        3、QPixmap加载的图片 QPixmap('logo.ico')
        """
        try:
            if isinstance(img, QPixmap):
                self.album_img = self.prepare_album_image(img)
            if isinstance(img, str):
                if img.lower().startswith('http'):
                    self.album_img = self.prepare_album_image(self.load_image(img))
                else:
                    self.album_img = self.prepare_album_image(img)
        except Exception as e:
            self.album_img = QPixmap()

    # 加载网络图片
    def load_image(self, url):
        try:
            response = requests.get(url)
            img_data = BytesIO(response.content).getvalue()
            pixmap = QPixmap()
            pixmap.loadFromData(img_data)
            return pixmap
        except Exception as e:
            pass

    def pause(self):
        """暂停旋转"""
        if self.is_rotating:
            self.timer.stop()
            self.is_rotating = False

    def start(self):
        """启动旋转"""
        if not self.is_rotating:
            self.timer.start(50)
            self.is_rotating = True

    def rotateDisc(self):
        self.angle = (self.angle + 1) % 360  # 每次旋转1度
        self.update()

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)
        painter.setRenderHint(QPainter.SmoothPixmapTransform)

        # 中心点
        center_x = self.width() / 2
        center_y = self.height() / 2

        # 绘制背景图,围绕自身中心旋转
        painter.save()
        painter.translate(center_x, center_y)
        painter.rotate(self.angle)
        painter.translate(-self.bg_img.width() / 2, -self.bg_img.height() / 2)
        painter.drawPixmap(0, 0, self.bg_img)
        painter.restore()

        # 绘制前景图,围绕自身中心旋转
        painter.save()
        painter.translate(center_x, center_y)
        painter.rotate(self.angle)
        painter.translate(-self.album_img.width() / 2, -self.album_img.height() / 2)

        # 创建一个圆形路径
        path = QPainterPath()
        path.addEllipse(0, 0, self.album_img.width(), self.album_img.height())
        painter.setClipPath(path)

        # 绘制被剪裁成圆形的前景图
        painter.drawPixmap(0, 0, self.album_img)
        painter.restore()

    def mousePressEvent(self, event):
        self.album_clicked.emit('这是一个信号')


class MainWindow(QWidget):
    def __init__(self):
        super(MainWindow, self).__init__()

        self.rotating_disc = AlbumRotatingIcon(bg_img_path='../../img/record.ico',
                                               album_img_path="../../img/logo.ico", size=64)

        layout = QHBoxLayout()
        layout.addWidget(self.rotating_disc)
        bu = QPushButton('点击修改')
        bu.clicked.connect(self.dd)
        layout.addWidget(bu)

        self.setLayout(layout)
        self.setWindowTitle("Music Player")

    def dd(self):
        self.rotating_disc.up_img('../../img/empty.png')


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

效果图:

修改后:

YXN-python

2024-11-05