Exemple #1
0
class SongInfoCardChute(QWidget):
    """ 
        歌曲卡滑槽,有三个歌曲卡在循环滑动,当前歌曲卡切换时就切换歌曲
        当前下标为0时,不能换到上一首, 当前下标为len-1时,不能换到下一首
    """

    # 当前歌曲切换信号
    currentIndexChanged = pyqtSignal([int], [str])
    # 显示和隐藏播放栏信号
    showPlayBarSignal = pyqtSignal()
    hidePlayBarSignal = pyqtSignal()
    # 切换到专辑界面
    switchToAlbumInterfaceSig = pyqtSignal(str, str)

    def __init__(self, parent=None, playlist=None):
        super().__init__(parent)
        self.shiftLeftTime = 0
        self.shiftRightTime = 0
        # 引用播放列表
        self.playlist = playlist
        self.currentIndex = 0
        self.songInfoCard_list = []
        # 设置发送信号标志位
        self.needToEmitSignal = True
        # 创建并行动画组
        self.parallelAniGroup = QParallelAnimationGroup(self)
        # 记录有待完成的动画
        self.__unCompleteShift_list = []
        # 初始化
        self.__initWidget()
        self.now = QDateTime.currentDateTime().toMSecsSinceEpoch()

    def __initWidget(self):
        """ 初始化小部件 """
        self.resize(1300, 970)
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.__createWidgets()
        for songInfoCard in self.songInfoCard_list:
            songInfoCard.resize(self.width(), 136)
        # 将信号连接到槽函数
        self.parallelAniGroup.finished.connect(self.__switchSongInfoCard)
        for songInfoCard in self.songInfoCard_list:
            songInfoCard.showPlayBarSignal.connect(self.__showPlayBar)
            songInfoCard.hidePlayBarSignal.connect(self.__hidePlayBar)
            songInfoCard.switchToAlbumInterfaceSig.connect(
                self.switchToAlbumInterfaceSig)

    def __createWidgets(self):
        """ 创建小部件 """
        # 创建三个歌曲信息卡,分别为last, current, next
        self.songInfoCard_list = [SongInfoCard(self) for i in range(3)]
        # 引用当前歌曲卡
        self.lastSongInfoCard = self.songInfoCard_list[0]
        self.curSongInfoCard = self.songInfoCard_list[1]
        self.nextSongInfoCard = self.songInfoCard_list[2]
        # 创建动画
        self.songInfoCardAni_list = [
            QPropertyAnimation(self.songInfoCard_list[i], b'geometry')
            for i in range(3)
        ]
        self.lastSongInfoCardAni = self.songInfoCardAni_list[0]
        self.curSongInfoCardAni = self.songInfoCardAni_list[1]
        self.nextSongInfoCardAni = self.songInfoCardAni_list[2]
        # 将动画添加到动画组中
        for ani in self.songInfoCardAni_list:
            self.parallelAniGroup.addAnimation(ani)
        # 先隐藏所有歌曲信息卡并设置位置
        for i in range(3):
            self.songInfoCard_list[i].move((i - 1) * self.width(),
                                           self.height() - 204)
            self.songInfoCard_list[i].hide()
        # 初始化歌曲卡
        if self.playlist:
            self.curSongInfoCard.updateCard(self.playlist[0])
            self.curSongInfoCard.show()
            if len(self.playlist) >= 2:
                self.nextSongInfoCard.show()
                self.nextSongInfoCard.updateCard(self.playlist[1])

    def mousePressEvent(self, e: QMouseEvent):
        """ 按钮按下时记录鼠标位置 """
        super().mousePressEvent(e)
        self.mousePressPosX = e.pos().x()
        self.lastMousePosX = e.pos().x()
        # 记下按下的时间
        self.mousePressTime = QDateTime.currentDateTime().toMSecsSinceEpoch()

    def mouseMoveEvent(self, e: QMouseEvent):
        """ 鼠标按下可拖动歌曲信息卡 """
        for songInfoCard in self.songInfoCard_list:
            songInfoCard.move(
                songInfoCard.x() - (self.lastMousePosX - e.pos().x()),
                songInfoCard.y())
        # 更新鼠标位置
        self.lastMousePosX = e.pos().x()

    def mouseReleaseEvent(self, e: QMouseEvent):
        """ 鼠标松开时重新设置歌曲卡位置 """
        # 记下松开的时间
        self.mouseReleaseTime = QDateTime.currentDateTime().toMSecsSinceEpoch()
        mouseDeltaTime = self.mouseReleaseTime - self.mousePressTime
        # self.mouseDeltaX > 0代表向右移动
        self.mouseDeltaX = self.lastMousePosX - self.mousePressPosX
        # 设置默认循环移位方式
        self.loopMode = SongInfoCardLoopMode.NO_LOOP
        if self.playlist:
            if len(self.playlist) == 1:
                # 只有1个歌曲卡时不管移动距离是多少都把该歌曲卡放回原位
                self.__restoreCardPosition()
            # 播放列表长度大于等于2
            elif len(self.playlist) >= 2:
                # 下标为0时右移或者下标为len-1左移都恢复原状
                if (self.currentIndex == 0 and self.mouseDeltaX > 0) or (
                        self.currentIndex == len(self.playlist) - 1
                        and self.mouseDeltaX < 0):
                    self.__restoreCardPosition()
                else:
                    if mouseDeltaTime < 360 and abs(self.mouseDeltaX) >= 120:
                        self.__cycleShift()
                    else:
                        if abs(self.mouseDeltaX) < int(self.width() / 2):
                            self.__restoreCardPosition()
                        else:
                            self.__cycleShift()

    def __cycleLeftShift(self):
        """ 循环左移 """
        self.loopMode = SongInfoCardLoopMode.CYCLE_LEFT_SHIFT
        self.__setAnimation(self.curSongInfoCardAni, self.curSongInfoCard,
                            -self.width())
        self.__setAnimation(self.nextSongInfoCardAni, self.nextSongInfoCard, 0)
        self.parallelAniGroup.removeAnimation(self.lastSongInfoCardAni)
        self.parallelAniGroup.start()
        # 发送更新背景信号
        self.currentIndexChanged[str].emit(
            self.nextSongInfoCard.albumCoverPath)

    def __cycleRightShift(self):
        """ 循环右移 """
        self.loopMode = SongInfoCardLoopMode.CYCLE_RIGHT_SHIFT
        self.__setAnimation(self.curSongInfoCardAni, self.curSongInfoCard,
                            self.width())
        self.__setAnimation(self.lastSongInfoCardAni, self.lastSongInfoCard, 0)
        self.parallelAniGroup.removeAnimation(self.nextSongInfoCardAni)
        self.parallelAniGroup.start()
        # 发送更新背景信号
        self.currentIndexChanged[str].emit(
            self.lastSongInfoCard.albumCoverPath)

    def __switchSongInfoCard(self):
        """ 交换对底层歌曲卡对象的引用 """
        # 循环左移
        if self.loopMode == SongInfoCardLoopMode.CYCLE_LEFT_SHIFT:
            self.__resetRef(moveDirection=0)
            # 更新动画组
            self.parallelAniGroup.addAnimation(self.lastSongInfoCardAni)
            # 移动底层对象
            self.__moveObject(
                self.songInfoCard_list[[2, 0, 1][self.shiftLeftTime]],
                self.width())
            # 更新下标
            self.currentIndex += 1
            if self.currentIndex != len(self.playlist) - 1:
                # 更新歌曲信息卡
                self.updateCards()
                self.nextSongInfoCard.show()
            else:
                self.nextSongInfoCard.hide()
            # 根据标志位决定是否发送下标更新信号
            if self.needToEmitSignal:
                self.currentIndexChanged[int].emit(self.currentIndex)
            else:
                self.needToEmitSignal = True
        # 循环右移
        elif self.loopMode == SongInfoCardLoopMode.CYCLE_RIGHT_SHIFT:
            self.__resetRef(moveDirection=1)
            # 更新动画组
            self.parallelAniGroup.addAnimation(self.nextSongInfoCardAni)
            # 移动底层对象
            self.__moveObject(
                self.songInfoCard_list[[0, 2, 1][self.shiftRightTime]],
                -self.width())
            # 更新下标
            self.currentIndex -= 1
            if self.currentIndex != 0:
                self.updateCards()
                self.lastSongInfoCard.show()
            else:
                self.lastSongInfoCard.hide()
            # 根据标志位决定是否发送下标更新信号
            if self.needToEmitSignal:
                self.currentIndexChanged[int].emit(self.currentIndex)
            else:
                self.needToEmitSignal = True
        # 完成未完成的移位动作
        if self.__unCompleteShift_list:
            index = self.__unCompleteShift_list.pop(0)
            self.needToEmitSignal = False
            self.__completeShift(index)

    def __cycleShift(self):
        """ 三卡片移动 """
        # 播放播放列表的上一首(右移歌曲卡)
        if self.mouseDeltaX > 0:
            self.__cycleRightShift()
        # 播放播放列表的下一首(左移歌曲卡)
        elif self.mouseDeltaX < 0:
            self.__cycleLeftShift()

    def __setAnimation(self, animation: QPropertyAnimation, songInfoCard,
                       endX):
        """ 设置动画 """
        animation.setEasingCurve(QEasingCurve.OutQuart)
        animation.setTargetObject(songInfoCard)
        animation.setDuration(500)
        # 设置起始值
        animation.setStartValue(
            QRect(songInfoCard.x(), songInfoCard.y(), songInfoCard.width(),
                  songInfoCard.height()))
        # 设置结束值
        animation.setEndValue(
            QRect(endX, songInfoCard.y(), songInfoCard.width(),
                  songInfoCard.height()))

    def __restoreCardPosition(self):
        """ 恢复卡片位置 """
        self.__setAnimation(self.curSongInfoCardAni, self.curSongInfoCard, 0)
        self.__setAnimation(self.nextSongInfoCardAni, self.nextSongInfoCard,
                            self.width())
        self.__setAnimation(self.lastSongInfoCardAni, self.lastSongInfoCard,
                            -self.width())
        self.parallelAniGroup.start()

    def updateCards(self):
        """ 更新三个歌曲信息卡 """
        if self.curSongInfoCard:
            self.curSongInfoCard.updateCard(self.playlist[self.currentIndex])
        if self.lastSongInfoCard and self.currentIndex >= 1:
            self.lastSongInfoCard.updateCard(self.playlist[self.currentIndex -
                                                           1])
        if self.nextSongInfoCard and self.currentIndex <= len(
                self.playlist) - 2:
            self.nextSongInfoCard.updateCard(self.playlist[self.currentIndex +
                                                           1])

    def setCurrentIndex(self, index):
        """ 更新当前下标并移动和更新歌曲信息卡 """
        # 移位完成后不发送信号
        self.needToEmitSignal = False
        if self.playlist:
            # 新的下标大于当前下标时,歌曲卡左移
            if index != self.currentIndex:
                if self.parallelAniGroup.state() != QAbstractAnimation.Running:
                    self.__completeShift(index)
                else:
                    self.__unCompleteShift_list.append(index)
            elif index == self.currentIndex:
                self.updateCards()
                self.needToEmitSignal = True

    def setPlaylist(self, playlist, isResetIndex: bool = True):
        """ 更新播放列表 """
        self.playlist = playlist
        self.currentIndex = 0 if isResetIndex else self.currentIndex
        self.lastSongInfoCard.hide()
        if playlist:
            self.curSongInfoCard.updateCard(self.playlist[self.currentIndex])
            self.currentIndexChanged[str].emit(
                self.curSongInfoCard.albumCoverPath)
            self.curSongInfoCard.show()
            if len(self.playlist) == 1:
                self.nextSongInfoCard.hide()
            else:
                self.nextSongInfoCard.show()
                self.nextSongInfoCard.updateCard(
                    self.playlist[self.currentIndex + 1])
        else:
            self.curSongInfoCard.hide()
            self.nextSongInfoCard.hide()

    def resizeEvent(self, e):
        """ 改变窗口大小时也改变歌曲卡的大小 """
        super().resizeEvent(e)
        for i in range(3):
            self.songInfoCard_list[i].resize(self.width(), 136)
            self.songInfoCard_list[i].adjustText()
        self.curSongInfoCard.move(0, self.height() - 204)
        self.lastSongInfoCard.move(-self.width(), self.height() - 204)
        self.nextSongInfoCard.move(self.width(), self.height() - 204)

    def __moveObject(self, songInfoCardObj, x):
        """ 移动底层对象 """
        songInfoCardObj.hide()
        songInfoCardObj.move(x, self.height() - 204)
        songInfoCardObj.show()

    def __resetRef(self, moveDirection=0):
        """ 设置变量对底层对象的引用,moveDirection = 0 代表左移,moveDirection = 1 代表右移 """
        # 循环左移
        if moveDirection == 0:
            self.shiftLeftTime = (self.shiftLeftTime + 1) % 3
            self.shiftRightTime = (self.shiftRightTime - 1) % 3
            if self.shiftLeftTime == 0:
                self.__resetRefIndex(0, 1, 2)
            elif self.shiftLeftTime == 1:
                self.__resetRefIndex(1, 2, 0)
            elif self.shiftLeftTime == 2:
                self.__resetRefIndex(2, 0, 1)
        # 循环右移
        elif moveDirection == 1:
            self.shiftLeftTime = (self.shiftLeftTime - 1) % 3
            self.shiftRightTime = (self.shiftRightTime + 1) % 3
            if self.shiftRightTime == 0:
                self.__resetRefIndex(0, 1, 2)
            elif self.shiftRightTime == 1:
                self.__resetRefIndex(2, 0, 1)
            elif self.shiftRightTime == 2:
                self.__resetRefIndex(1, 2, 0)

    def __resetRefIndex(self, lastIndex, curIndex, nextIndex):
        """ refsetFunc的子函数 """
        self.curSongInfoCard = self.songInfoCard_list[curIndex]
        self.lastSongInfoCard = self.songInfoCard_list[lastIndex]
        self.nextSongInfoCard = self.songInfoCard_list[nextIndex]

    def __showPlayBar(self):
        """ 显示播放栏 """
        self.showPlayBarSignal.emit()
        for songInfoCard in self.songInfoCard_list:
            songInfoCard.isPlayBarVisible = True

    def __hidePlayBar(self):
        """ 隐藏播放栏 """
        self.hidePlayBarSignal.emit()
        for songInfoCard in self.songInfoCard_list:
            songInfoCard.isPlayBarVisible = False

    def stopSongInfoCardTimer(self):
        """ 停止歌曲信息卡的计时器 """
        for songInfoCard in self.songInfoCard_list:
            songInfoCard.timer.stop()

    def startSongInfoCardTimer(self):
        """ 打开歌曲信息卡的计时器 """
        self.curSongInfoCard.timer.start()

    def __completeShift(self, index):
        """ 完成移位,只在调用setCurrentIndex时调用 """
        if index > self.currentIndex:
            self.currentIndex = index - 1
            self.nextSongInfoCard.updateCard(self.playlist[index])
            self.__cycleLeftShift()
        elif index < self.currentIndex:
            self.currentIndex = index + 1
            self.lastSongInfoCard.updateCard(self.playlist[index])
            self.__cycleRightShift()
Exemple #2
0
class SmallestPlayModeInterface(QWidget):
    """ 最小播放模式界面 """

    CYCLE_LEFT_SHIFT = 0
    CYCLE_RIGHT_SHIFT = 1

    def __init__(self, playlist: list, parent=None):
        super().__init__(parent)
        self.playlist = playlist
        self.currentIndex = 0
        self.shiftLeftTime = 0
        self.shiftRightTime = 0
        self.songInfoCard_list = []
        self.__unCompleteShift_list = []
        # 创建按钮
        self.playButton = PlayButton(
            [
                r"app\resource\images\smallest_play_mode\播放_45_45.png",
                r"app\resource\images\smallest_play_mode\暂停_45_45.png",
            ],
            self,
        )
        self.lastSongButton = SmallestPlayModeButton(
            r"app\resource\images\smallest_play_mode\上一首_45_45.png", self)
        self.nextSongButton = SmallestPlayModeButton(
            r"app\resource\images\smallest_play_mode\下一首_45_45.png", self)
        self.exitSmallestModeButton = BasicCircleButton(
            r"app\resource\images\playing_interface\最小模式播放_47_47.png", self)
        self.progressBar = QSlider(Qt.Horizontal, self)
        self.aniGroup = QParallelAnimationGroup(self)
        # 创建歌曲信息卡
        self.__createSongInfoCards()
        # 初始化
        self.__initWidget()

    def __initWidget(self):
        """ 初始化界面 """
        self.resize(350, 350)
        self.setMinimumSize(206, 197)
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.setObjectName("smallestModeInterface")
        self.progressBar.setObjectName("smallestModeSlider")
        self.progressBar.installEventFilter(self)
        self.aniGroup.finished.connect(self.__switchSongInfoCard)
        self.__setQss()

    def __createSongInfoCards(self):
        """ 创建歌曲信息卡 """
        # 创建三个歌曲信息卡,分别为last, current, next
        self.songInfoCard_list = [SongInfoCard(parent=self) for i in range(3)]
        # 引用当前歌曲卡
        self.lastSongInfoCard = self.songInfoCard_list[0]  # type:SongInfoCard
        self.curSongInfoCard = self.songInfoCard_list[1]  # type:SongInfoCard
        self.nextSongInfoCard = self.songInfoCard_list[2]  # type:SongInfoCard
        # 创建动画
        self.songInfoCardAni_list = [
            QPropertyAnimation(self.songInfoCard_list[i], b"geometry")
            for i in range(3)
        ]
        self.lastSongInfoCardAni = self.songInfoCardAni_list[0]
        self.curSongInfoCardAni = self.songInfoCardAni_list[1]
        self.nextSongInfoCardAni = self.songInfoCardAni_list[2]
        # 将动画添加到动画组中
        for ani in self.songInfoCardAni_list:
            self.aniGroup.addAnimation(ani)
        # 初始化歌曲卡
        for i in range(3):
            self.songInfoCard_list[i].move((i - 1) * self.width(),
                                           self.height() - 106)
        if self.playlist:
            self.curSongInfoCard.updateCard(self.playlist[0])
            if len(self.playlist) >= 2:
                self.nextSongInfoCard.updateCard(self.playlist[1])

    def resizeEvent(self, e):
        """ 改变窗口大小时调整按钮位置和标签宽度 """
        self.progressBar.resize(self.width(), 5)
        self.progressBar.move(0, self.height() - 5)
        self.exitSmallestModeButton.move(
            self.width() - 7 - self.exitSmallestModeButton.width(),
            self.height() - 7 - self.exitSmallestModeButton.height(),
        )
        self.playButton.move(
            int(self.width() / 2 - self.playButton.width() / 2),
            int(self.height() / 2 - self.playButton.height() / 2),
        )
        self.lastSongButton.move(self.playButton.x() - 75, self.playButton.y())
        self.nextSongButton.move(self.playButton.x() + 75, self.playButton.y())
        # 所有歌曲信息卡设置位置
        for i in range(3):
            self.songInfoCard_list[i].resize(
                self.width(), self.songInfoCard_list[i].height())
        self.curSongInfoCard.move(0, self.height() - 106)
        self.lastSongInfoCard.move(-self.width(), self.height() - 106)
        self.nextSongInfoCard.move(self.width(), self.height() - 106)
        # 高度太小时隐藏歌曲信息卡
        if self.height() <= 320:
            if self.curSongInfoCard.isVisible():
                self.curSongInfoCard.aniHide()
            self.lastSongInfoCard.hide()
            self.nextSongInfoCard.hide()
        elif self.height() > 320:
            if not self.curSongInfoCard.isVisible():
                self.curSongInfoCard.aniShow()
            else:
                self.curSongInfoCard.show()
            self.lastSongInfoCard.show()
            self.nextSongInfoCard.show()

    def __setQss(self):
        """ 设置层叠样式 """
        with open(r"app\resource\css\playInterface.qss",
                  encoding="utf-8") as f:
            self.setStyleSheet(f.read())

    def eventFilter(self, obj, e: QEvent):
        """ 过滤事件 """
        if obj == self.progressBar:
            if e.type() in [
                    QEvent.MouseButtonPress, QEvent.MouseButtonDblClick
            ]:
                return True
        return super().eventFilter(obj, e)

    def __cycleLeftShift(self):
        """ 循环左移 """
        self.loopMode = self.CYCLE_LEFT_SHIFT
        self.__setAnimation(self.curSongInfoCardAni, self.curSongInfoCard,
                            -self.width())
        self.__setAnimation(self.nextSongInfoCardAni, self.nextSongInfoCard, 0)
        self.aniGroup.removeAnimation(self.lastSongInfoCardAni)
        self.aniGroup.start()

    def __cycleRightShift(self):
        """ 循环右移 """
        self.loopMode = self.CYCLE_RIGHT_SHIFT
        self.__setAnimation(self.curSongInfoCardAni, self.curSongInfoCard,
                            self.width())
        self.__setAnimation(self.lastSongInfoCardAni, self.lastSongInfoCard, 0)
        self.aniGroup.removeAnimation(self.nextSongInfoCardAni)
        self.aniGroup.start()

    def __setAnimation(self, animation: QPropertyAnimation, songInfoCard,
                       endX):
        """ 设置动画 """
        animation.setEasingCurve(QEasingCurve.OutQuart)
        animation.setTargetObject(songInfoCard)
        animation.setDuration(500)
        # 设置起始值
        animation.setStartValue(
            QRect(
                songInfoCard.x(),
                songInfoCard.y(),
                songInfoCard.width(),
                songInfoCard.height(),
            ))
        # 设置结束值
        animation.setEndValue(
            QRect(endX, songInfoCard.y(), songInfoCard.width(),
                  songInfoCard.height()))

    def __switchSongInfoCard(self):
        """ 交换对底层歌曲卡对象的引用 """
        # 循环左移
        if self.loopMode == self.CYCLE_LEFT_SHIFT:
            self.__resetRef(moveDirection=0)
            # 更新动画组
            self.aniGroup.addAnimation(self.lastSongInfoCardAni)
            # 移动底层对象
            self.songInfoCard_list[[2, 0, 1][self.shiftLeftTime]].move(
                self.width(),
                self.height() - 106)
            # 更新下标
            self.currentIndex += 1
            if self.currentIndex != len(self.playlist) - 1:
                # 更新歌曲信息卡
                self.updateCards()
        # 循环右移
        elif self.loopMode == self.CYCLE_RIGHT_SHIFT:
            self.__resetRef(moveDirection=1)
            # 更新动画组
            self.aniGroup.addAnimation(self.nextSongInfoCardAni)
            # 移动底层对象
            self.songInfoCard_list[[0, 2, 1][self.shiftRightTime]].move(
                -self.width(),
                self.height() - 106)
            # 更新下标
            self.currentIndex -= 1
            if self.currentIndex != 0:
                self.updateCards()
        # 完成未完成的移位动作
        if self.__unCompleteShift_list:
            index = self.__unCompleteShift_list.pop(0)
            self.__completeShift(index)

    def updateCards(self):
        """ 更新三个歌曲信息卡 """
        self.curSongInfoCard.updateCard(self.playlist[self.currentIndex])
        if self.currentIndex >= 1:
            self.lastSongInfoCard.updateCard(self.playlist[self.currentIndex -
                                                           1])
        if self.currentIndex <= len(self.playlist) - 2:
            self.nextSongInfoCard.updateCard(self.playlist[self.currentIndex +
                                                           1])

    def __resetRef(self, moveDirection=0):
        """ 设置变量对底层对象的引用,moveDirection = 0 代表左移,moveDirection = 1 代表右移 """
        # 循环左移
        if moveDirection == 0:
            self.shiftLeftTime = (self.shiftLeftTime + 1) % 3
            self.shiftRightTime = (self.shiftRightTime - 1) % 3
            if self.shiftLeftTime == 0:
                self.__resetRefIndex(0, 1, 2)
            elif self.shiftLeftTime == 1:
                self.__resetRefIndex(1, 2, 0)
            elif self.shiftLeftTime == 2:
                self.__resetRefIndex(2, 0, 1)
        # 循环右移
        elif moveDirection == 1:
            self.shiftLeftTime = (self.shiftLeftTime - 1) % 3
            self.shiftRightTime = (self.shiftRightTime + 1) % 3
            if self.shiftRightTime == 0:
                self.__resetRefIndex(0, 1, 2)
            elif self.shiftRightTime == 1:
                self.__resetRefIndex(2, 0, 1)
            elif self.shiftRightTime == 2:
                self.__resetRefIndex(1, 2, 0)

    def __resetRefIndex(self, lastIndex, curIndex, nextIndex):
        """ refsetFunc的子函数 """
        self.curSongInfoCard = self.songInfoCard_list[curIndex]
        self.lastSongInfoCard = self.songInfoCard_list[lastIndex]
        self.nextSongInfoCard = self.songInfoCard_list[nextIndex]

    def setCurrentIndex(self, index):
        """ 更新当前下标并移动和更新歌曲信息卡 """
        if self.playlist:
            # 新的下标大于当前下标时,歌曲卡左移
            if index != self.currentIndex:
                if self.aniGroup.state() != QAbstractAnimation.Running:
                    self.__completeShift(index)
                else:
                    self.__unCompleteShift_list.append(index)
            elif index == self.currentIndex:
                self.updateCards()
                self.needToEmitSignal = True

    def setPlaylist(self, playlist, isResetIndex: bool = True):
        """ 更新播放列表 """
        self.playlist = playlist
        self.currentIndex = 0 if isResetIndex else self.currentIndex
        if playlist:
            self.curSongInfoCard.updateCard(self.playlist[0])
            self.curSongInfoCard.show()
            if len(self.playlist) > 1:
                self.nextSongInfoCard.updateCard(self.playlist[1])
        else:
            self.curSongInfoCard.hide()

    def __completeShift(self, index):
        """ 完成移位,只在调用setCurrentIndex时调用 """
        if index > self.currentIndex:
            self.currentIndex = index - 1
            self.nextSongInfoCard.updateCard(self.playlist[index])
            self.__cycleLeftShift()
        elif index < self.currentIndex:
            self.currentIndex = index + 1
            self.lastSongInfoCard.updateCard(self.playlist[index])
            self.__cycleRightShift()