예제 #1
0
class AnimateWindowOpacity:
    def __init__(self,
                 widget: QtWidgets.QWidget,
                 duration: int,
                 start_value: float = 0.8,
                 end_value: float = 1.0):
        self.widget = widget
        self.duration = duration
        self.animation = QPropertyAnimation(self.widget, b"windowOpacity")
        self.start_value, self.end_value = start_value, end_value
        self.setup_animation(self.start_value, self.end_value)

    def setup_animation(self,
                        start_value: float = 0.0,
                        end_value: float = 1.0,
                        duration: int = 0):
        if not duration:
            duration = self.duration

        self.animation.setDuration(duration)
        self.animation.setKeyValueAt(0.0, start_value)
        self.animation.setKeyValueAt(1.0, end_value)
        self.animation.setEasingCurve(QEasingCurve.OutCubic)

    def fade_in(self, duration: int = 0):
        if self.widget.windowOpacity() >= self.end_value:
            return False

        self.setup_animation(self.start_value, self.end_value, duration)
        self.play()
        return True

    def fade_out(self, duration: int = 0):
        if self.widget.windowOpacity() <= self.start_value:
            return False

        self.setup_animation(self.end_value, self.start_value, duration)
        self.play()
        return True

    def play(self):
        if self.animation.state() != QAbstractAnimation.Running:
            self.animation.start()
예제 #2
0
class Eye(QWidget):
    def __init__(self, *args, **kwargs):
        QWidget.__init__(self, *args, **kwargs)
        self.body_color = QColor(0xffffff)
        self.border_color = QColor(0x000000)
        self.border_size = 0.02

        self.iris_size = 0.4
        self.watch_direction = (0.0, 0.0)

        self.iris = Iris(QColor(0x00aa00), parent=self)
        self.iris_move_anim = QPropertyAnimation(
            self.iris, b'pos')  # Animation for iris position
        self.iris_move_anim.setDuration(100)
        self.iris_size_anim = QPropertyAnimation(
            self.iris, b'pupil_size')  # Animation for pupil size
        self.iris_size_anim.setDuration(500)
        self.resize_iris()

    def resize_iris(self):
        pupil_size = int(min(self.width(), self.height()) * self.iris_size)
        self.iris.setFixedSize(pupil_size, pupil_size)
        self.set_watch_direction(*self.watch_direction, animate=False)

    def resizeEvent(self, event: QResizeEvent):
        self.resize_iris()

    def paintEvent(self, event):
        size = min(self.width(), self.height())
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)
        painter.translate(self.width() / 2, self.height() / 2)

        # draw border around eye
        painter.setBrush(QBrush(self.border_color))
        painter.drawEllipse(QPointF(0, 0), size / 2, size / 2)

        # draw sclera (white part of eyes)
        painter.setBrush(QBrush(self.body_color))
        body_size = size * (1 - self.border_size) * 0.5
        painter.drawEllipse(QPointF(0, 0), body_size, body_size)

    @property
    def radius(self):
        return min(self.width(), self.height()) / 2

    @property
    def body_radius(self):
        return self.radius * (1 - self.border_size)

    @staticmethod
    def cart2pol(x, y):
        """Convert cartesian coordinate to polar"""
        # https://stackoverflow.com/a/26757297/8181134
        mag = np.sqrt(x**2 + y**2)
        angle = np.arctan2(y, x)
        return (mag, angle)

    @staticmethod
    def pol2cart(mag, angle):
        """Convert polar coordinate to cartesian"""
        # https://stackoverflow.com/a/26757297/8181134
        x = mag * np.cos(angle)
        y = mag * np.sin(angle)
        return (x, y)

    def set_watch_direction(self, horizontal, vertical, animate=True):
        """ Move the eyes to the specified direction
        :param horizontal: float [-1 1]
        :param vertical: float [-1 1]
        """
        self.watch_direction = (horizontal, vertical)
        mag, angle = self.cart2pol(horizontal, vertical)
        mag = np.clip(mag, 0, 1)  # Limit the magnitude to max 1
        mag *= (self.body_radius - self.iris.radius
                )  # Max value for mag is so the edge of iris hits edge of eye
        x, y = self.pol2cart(mag, angle)

        x += (self.width() /
              2) - self.iris.radius  # Position of top-left corner of iris
        y += (self.height() / 2) - self.iris.radius

        if self.iris_move_anim.state() != QPropertyAnimation.Stopped:
            self.iris_move_anim.stop()
        if animate:
            self.iris_move_anim.setStartValue(self.iris.pos())
            self.iris_move_anim.setEndValue(QPointF(x, y))
            QTimer.singleShot(0, self.iris_move_anim.start)
        else:
            QTimer.singleShot(0, lambda x=x, y=y: self.iris.move(x, y))

    def set_pupil_size(self, size: float):
        """Set the pupil size
        :arg size: Size of the pupil [0..1]
        """
        self.iris_size_anim.stop()
        self.iris_size_anim.setStartValue(self.iris.pupil_size)
        self.iris_size_anim.setEndValue(size)
        QTimer.singleShot(0, self.iris_size_anim.start)
예제 #3
0
class AnimatedToggle(Toggle):

    _transparent_pen = QPen(Qt.transparent)
    _light_grey_pen = QPen(Qt.lightGray)

    def __init__(self,
                 *args,
                 pulse_unchecked_color="#44999999",
                 pulse_checked_color="#4400B0EE",
                 **kwargs):

        self._pulse_radius = 0

        super().__init__(*args, **kwargs)

        self.animation = QPropertyAnimation(self, b"handle_position", self)
        self.animation.setEasingCurve(QEasingCurve.InOutCubic)
        self.animation.setDuration(200)  # time in ms

        self.pulse_anim = QPropertyAnimation(self, b"pulse_radius", self)
        self.pulse_anim.setDuration(350)  # time in ms
        self.pulse_anim.setStartValue(10)
        self.pulse_anim.setEndValue(20)

        self.animations_group = QSequentialAnimationGroup()
        self.animations_group.addAnimation(self.animation)
        self.animations_group.addAnimation(self.pulse_anim)

        self._pulse_unchecked_animation = QBrush(QColor(pulse_unchecked_color))
        self._pulse_checked_animation = QBrush(QColor(pulse_checked_color))

    @Slot(int)
    def handle_state_change(self, value):
        self.animations_group.stop()
        if value:
            self.animation.setEndValue(1)
        else:
            self.animation.setEndValue(0)
        self.animations_group.start()

    def paintEvent(self, e: QPaintEvent):

        contRect = self.contentsRect()
        handleRadius = round(0.24 * contRect.height())

        p = QPainter(self)
        p.setRenderHint(QPainter.Antialiasing)

        p.setPen(self._transparent_pen)
        barRect = QRectF(0, 0,
                         contRect.width() - handleRadius,
                         0.40 * contRect.height())
        barRect.moveCenter(contRect.center())
        rounding = barRect.height() / 2

        # the handle will move along this line
        trailLength = contRect.width() - 2 * handleRadius

        xPos = contRect.x(
        ) + handleRadius + trailLength * self._handle_position

        if self.pulse_anim.state() == QPropertyAnimation.Running:
            p.setBrush(self._pulse_checked_animation if self.isChecked(
            ) else self._pulse_unchecked_animation)
            p.drawEllipse(QPointF(xPos,
                                  barRect.center().y()), self._pulse_radius,
                          self._pulse_radius)

        if self.isChecked():
            p.setBrush(self._bar_checked_brush)
            p.drawRoundedRect(barRect, rounding, rounding)
            p.setBrush(self._handle_checked_brush)

        else:
            p.setBrush(self._bar_brush)
            p.drawRoundedRect(barRect, rounding, rounding)
            p.setPen(self._light_grey_pen)
            p.setBrush(self._handle_brush)

        p.drawEllipse(QPointF(xPos,
                              barRect.center().y()), handleRadius,
                      handleRadius)

        p.end()
예제 #4
0
class StackedWidgetSlideOverAnimator(AbstractAnimator):
    m_direction: AnimationDirection
    m_coveredWidget: QWidget
    m_decorator: StackedWidgetSlideOverDecorator
    m_animation: QPropertyAnimation

    def __init__(self, _container, _widgetForSlide):
        super(StackedWidgetSlideOverAnimator, self).__init__(_container)

        self.m_direction = AnimationDirection.FromLeftToRight
        self.m_coveredWidget = _container.currentWidget()
        self.m_decorator = StackedWidgetSlideOverDecorator(
            _container, _widgetForGrab=_widgetForSlide)
        self.m_animation = QPropertyAnimation(self.m_decorator, b"pos")

        _container.installEventFilter(self)

        self.m_animation.setDuration(400)

        self.m_decorator.hide()

        def finished():
            self.setAnimatedStopped()

            if self.isAnimatedForward():
                _container.setCurrentWidget(_widgetForSlide)
            self.m_decorator.hide()

        self.m_animation.finished.connect(finished)

    def updateCoveredWidget(self):
        self.m_coveredWidget = self.stackedWidget().currentWidget()

    def setAnimationDirection(self, _direction):
        if self.m_direction != _direction:
            self.m_direction = _direction

    def animationDuration(self):
        return self.m_animation.duration()

    def animateForward(self):
        self.slideOverIn()

    def slideOverIn(self):
        if self.isAnimated() and self.isAnimatedForward():
            return
        self.setAnimatedForward()

        self.m_decorator.grabWidget()

        startPos = QPoint()
        finalPos = QPoint()

        if self.m_direction == AnimationDirection.FromLeftToRight:
            startPos.setX(-1 * self.stackedWidget().width())
        if self.m_direction == AnimationDirection.FromRightToLeft:
            startPos.setX(self.stackedWidget().width())
        if self.m_direction == AnimationDirection.FromTopToBottom:
            startPos.setY(-1 * self.stackedWidget().height())
        if self.m_direction == AnimationDirection.FromBottomToTop:
            startPos.setY(self.stackedWidget().height())

        self.m_decorator.show()
        self.m_decorator.raise_()

        if self.m_animation.state() == QPropertyAnimation.Running:
            self.m_animation.pause()
            self.m_animation.setDirection(QPropertyAnimation.Backward)
            self.m_animation.resume()
        else:
            self.m_animation.setEasingCurve(QEasingCurve.InOutExpo)
            self.m_animation.setDirection(QPropertyAnimation.Forward)
            self.m_animation.setStartValue(startPos)
            self.m_animation.setEndValue(finalPos)

            self.m_animation.start()

    def animateBackward(self):
        self.slideOverOut()

    def slideOverOut(self):
        if self.isAnimated() and self.isAnimatedBackward():
            return
        self.setAnimatedBackward()

        self.m_decorator.grabWidget()

        startPos = QPoint()
        finalPos = QPoint()

        if self.m_direction == AnimationDirection.FromLeftToRight:
            finalPos.setX(-1 * self.stackedWidget().width())
        if self.m_direction == AnimationDirection.FromRightToLeft:
            finalPos.setX(self.stackedWidget().width())
        if self.m_direction == AnimationDirection.FromTopToBottom:
            finalPos.setY(-1 * self.stackedWidget().height())
        if self.m_direction == AnimationDirection.FromBottomToTop:
            finalPos.setY(self.stackedWidget().height())

        if isinstance(self.stackedWidget(), type(self)):
            self.stackedWidget().setCurrentWidget(self.m_coveredWidget)

        self.m_decorator.show()
        self.m_decorator.raise_()

        if self.m_animation.state() == QPropertyAnimation.Running:
            self.m_animation.pause()
            self.m_animation.setDirection(QPropertyAnimation.Backward)
            self.m_animation.resume()
        else:
            self.m_animation.setEasingCurve(QEasingCurve.InOutExpo)
            self.m_animation.setDirection(QPropertyAnimation.Forward)
            self.m_animation.setStartValue(startPos)
            self.m_animation.setEndValue(finalPos)

            self.m_animation.start()

    def eventFilter(self, _object, _event):
        if _object == self.stackedWidget() and _event.type(
        ) == QEvent.Resize and self.m_decorator.isVisible():
            self.m_decorator.grabWidget()

        return QWidget.eventFilter(self, _object, _event)

    def stackedWidget(self):
        return self.parent()
예제 #5
0
class ScreensharingToolbox(base_class, ui_class):
    exposedPixels = 3

    def __init__(self, parent):
        super(ScreensharingToolbox, self).__init__(parent)
        with Resources.directory:
            self.setupUi()
        parent.installEventFilter(self)
        self.animation = QPropertyAnimation(self, 'pos')
        self.animation.setDuration(250)
        self.animation.setDirection(QPropertyAnimation.Forward)
        self.animation.setEasingCurve(
            QEasingCurve.Linear)  # or OutCirc with 300ms
        self.retract_timer = QTimer(self)
        self.retract_timer.setInterval(3000)
        self.retract_timer.setSingleShot(True)
        self.retract_timer.timeout.connect(self.retract)
        self.resize(self.size().expandedTo(self.toolbox_layout.minimumSize()))

    def setupUi(self):
        super(ScreensharingToolbox, self).setupUi(self)

        # fix the SVG icons, as the generated code loads them as pixmaps, losing their ability to scale -Dan
        scale_icon = QIcon()
        scale_icon.addFile(Resources.get('icons/scale.svg'),
                           mode=QIcon.Normal,
                           state=QIcon.Off)
        viewonly_icon = QIcon()
        viewonly_icon.addFile(Resources.get('icons/viewonly.svg'),
                              mode=QIcon.Normal,
                              state=QIcon.Off)
        screenshot_icon = QIcon()
        screenshot_icon.addFile(Resources.get('icons/screenshot.svg'),
                                mode=QIcon.Normal,
                                state=QIcon.Off)
        fullscreen_icon = QIcon()
        fullscreen_icon.addFile(Resources.get('icons/fullscreen.svg'),
                                mode=QIcon.Normal,
                                state=QIcon.Off)
        fullscreen_icon.addFile(Resources.get('icons/fullscreen-exit.svg'),
                                mode=QIcon.Normal,
                                state=QIcon.On)
        fullscreen_icon.addFile(Resources.get('icons/fullscreen-exit.svg'),
                                mode=QIcon.Active,
                                state=QIcon.On)
        fullscreen_icon.addFile(Resources.get('icons/fullscreen-exit.svg'),
                                mode=QIcon.Disabled,
                                state=QIcon.On)
        fullscreen_icon.addFile(Resources.get('icons/fullscreen-exit.svg'),
                                mode=QIcon.Selected,
                                state=QIcon.On)
        minimize_icon = QIcon()
        minimize_icon.addFile(Resources.get('icons/minimize.svg'),
                              mode=QIcon.Normal,
                              state=QIcon.Off)
        minimize_icon.addFile(Resources.get('icons/minimize-active.svg'),
                              mode=QIcon.Active,
                              state=QIcon.Off)
        close_icon = QIcon()
        close_icon.addFile(Resources.get('icons/close.svg'),
                           mode=QIcon.Normal,
                           state=QIcon.Off)
        close_icon.addFile(Resources.get('icons/close-active.svg'),
                           mode=QIcon.Active,
                           state=QIcon.Off)

        self.scale_action.setIcon(scale_icon)
        self.viewonly_action.setIcon(viewonly_icon)
        self.screenshot_action.setIcon(screenshot_icon)
        self.fullscreen_action.setIcon(fullscreen_icon)
        self.minimize_action.setIcon(minimize_icon)
        self.close_action.setIcon(close_icon)

        self.scale_button.setIcon(scale_icon)
        self.viewonly_button.setIcon(viewonly_icon)
        self.screenshot_button.setIcon(screenshot_icon)
        self.fullscreen_button.setIcon(fullscreen_icon)
        self.minimize_button.setIcon(minimize_icon)
        self.close_button.setIcon(close_icon)

        self.scale_button.setDefaultAction(self.scale_action)
        self.viewonly_button.setDefaultAction(self.viewonly_action)
        self.screenshot_button.setDefaultAction(self.screenshot_action)
        self.fullscreen_button.setDefaultAction(self.fullscreen_action)
        self.minimize_button.setDefaultAction(self.minimize_action)
        self.close_button.setDefaultAction(self.close_action)

        self.color_depth_button.clear()
        self.color_depth_button.addItem('Default Color Depth', ServerDefault)
        self.color_depth_button.addItem('TrueColor (24 bits)', TrueColor)
        self.color_depth_button.addItem('HighColor (16 bits)', HighColor)
        self.color_depth_button.addItem('LowColor (8 bits)', LowColor)

    def eventFilter(self, watched, event):
        if watched is self.parent() and event.type() == QEvent.Resize:
            new_x = (watched.width() - self.width()) / 2
            self.move(new_x, self.y())
            self.animation.setStartValue(
                QPoint(new_x, -self.height() + self.exposedPixels))
            self.animation.setEndValue(QPoint(new_x, 0))
        return False

    def enterEvent(self, event):
        super(ScreensharingToolbox, self).enterEvent(event)
        self.retract_timer.stop()
        self.expose()

    def leaveEvent(self, event):
        super(ScreensharingToolbox, self).leaveEvent(event)
        self.retract_timer.start()

    def paintEvent(self, event):  # make the widget style aware
        option = QStyleOption()
        option.initFrom(self)
        painter = QStylePainter(self)
        painter.drawPrimitive(QStyle.PE_Widget, option)

    def expose(self):
        if self.animation.state(
        ) == QPropertyAnimation.Running and self.animation.direction(
        ) == QPropertyAnimation.Forward:
            return
        elif self.animation.state() == QPropertyAnimation.Stopped and self.pos(
        ) == self.animation.endValue():
            return
        self.animation.setDirection(QPropertyAnimation.Forward)
        self.animation.start()

    def retract(self):
        if self.animation.state(
        ) == QPropertyAnimation.Running and self.animation.direction(
        ) == QPropertyAnimation.Backward:
            return
        elif self.animation.state() == QPropertyAnimation.Stopped and self.pos(
        ) == self.animation.startValue():
            return
        self.animation.setDirection(QPropertyAnimation.Backward)
        self.animation.start()
예제 #6
0
class PlayingInterface(QWidget):
    """ 正在播放界面 """

    nextSongSig = pyqtSignal()  # 点击下一首或者上一首按钮时由主界面的播放列表决定下一首的Index
    lastSongSig = pyqtSignal()
    switchPlayStateSig = pyqtSignal()
    randomPlayAllSignal = pyqtSignal()
    removeMediaSignal = pyqtSignal(int)
    # 点击歌曲卡或者滑动歌曲信息卡滑槽时直接设置新的index,index由自己决定
    currentIndexChanged = pyqtSignal(int)
    switchToAlbumInterfaceSig = pyqtSignal(str, str)
    # 发出进入最小模式的信号
    smallestModeStateChanged = pyqtSignal(bool)
    # 退出全屏信号
    exitFullScreenSig = pyqtSignal()

    def __init__(self, playlist: list = None, parent=None):
        super().__init__(parent)
        self.playlist = playlist.copy()
        self.currentIndex = 0
        self.isPlaylistVisible = False
        # 创建小部件
        self.blurPixmap = None
        self.blurBackgroundPic = QLabel(self)
        self.blurCoverThread = BlurCoverThread(self)
        self.songInfoCardChute = SongInfoCardChute(self, self.playlist)
        self.parallelAniGroup = QParallelAnimationGroup(self)
        self.songInfoCardChuteAni = QPropertyAnimation(self.songInfoCardChute,
                                                       b"geometry")
        self.playBar = PlayBar(self)
        self.songListWidget = SongListWidget(self.playlist, self)
        self.smallestModeInterface = SmallestPlayModeInterface(playlist, self)
        self.playBarAni = QPropertyAnimation(self.playBar, b"geometry")
        self.songListWidgetAni = QPropertyAnimation(self.songListWidget,
                                                    b"geometry")
        self.guideLabel = QLabel("在这里,你将看到正在播放的歌曲以及即将播放的歌曲。", self)
        self.randomPlayAllButton = ThreeStatePushButton(
            {
                "normal":
                r"app\resource\images\playing_interface\全部随机播放_normal.png",
                "hover":
                r"app\resource\images\playing_interface\全部随机播放_hover.png",
                "pressed":
                r"app\resource\images\playing_interface\全部随机播放_pressed.png",
            }, " 随机播放你收藏中的所有内容", (30, 22), self)
        # 创建定时器
        self.showPlaylistTimer = QTimer(self)
        self.hidePlaylistTimer = QTimer(self)
        # 初始化
        self.__initWidget()

    def __initWidget(self):
        """ 初始化小部件 """
        self.resize(1100, 870)
        self.currentSmallestModeSize = QSize(340, 340)
        self.setAttribute(Qt.WA_StyledBackground)
        self.guideLabel.move(45, 62)
        self.randomPlayAllButton.move(45, 117)
        self.playBar.move(0, self.height() - self.playBar.height())
        # 隐藏部件
        self.smallestModeInterface.hide()
        self.randomPlayAllButton.hide()
        self.guideLabel.hide()
        self.playBar.hide()
        # 设置层叠样式
        self.setObjectName("playingInterface")
        self.guideLabel.setObjectName("guideLabel")
        self.randomPlayAllButton.setObjectName("randomPlayAllButton")
        self.__setQss()
        # 开启磨砂线程
        if self.playlist:
            self.startBlurThread(
                self.songInfoCardChute.curSongInfoCard.albumCoverPath)
        # 将信号连接到槽
        self.__connectSignalToSlot()
        # 初始化动画
        self.playBarAni.setDuration(350)
        self.songListWidgetAni.setDuration(350)
        self.songListWidgetAni.setEasingCurve(QEasingCurve.InOutQuad)
        self.playBarAni.setEasingCurve(QEasingCurve.InOutQuad)
        self.parallelAniGroup.addAnimation(self.playBarAni)
        self.parallelAniGroup.addAnimation(self.songInfoCardChuteAni)
        # 初始化定时器
        self.showPlaylistTimer.setInterval(120)
        self.hidePlaylistTimer.setInterval(120)
        self.showPlaylistTimer.timeout.connect(self.showPlayListTimerSlot)
        self.hidePlaylistTimer.timeout.connect(self.hidePlayListTimerSlot)

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

    def setBlurPixmap(self, blurPixmap):
        """ 设置磨砂pixmap """
        self.blurPixmap = blurPixmap
        # 更新背景
        self.__resizeBlurPixmap()

    def __resizeBlurPixmap(self):
        """ 调整背景图尺寸 """
        maxWidth = max(self.width(), self.height())
        if self.blurPixmap:
            self.blurBackgroundPic.setPixmap(
                self.blurPixmap.scaled(
                    maxWidth,
                    maxWidth,
                    Qt.KeepAspectRatioByExpanding,
                    Qt.SmoothTransformation,
                ))

    def startBlurThread(self, albumCoverPath):
        """ 开启磨砂线程 """
        blurRadius = [6, 40][self.smallestModeInterface.isVisible()]
        self.blurCoverThread.setTargetCover(albumCoverPath,
                                            blurRadius=blurRadius)
        self.blurCoverThread.start()

    def resizeEvent(self, e):
        """ 改变尺寸时也改变小部件的大小 """
        super().resizeEvent(e)
        self.__resizeBlurPixmap()
        self.songInfoCardChute.resize(self.size())
        self.blurBackgroundPic.setFixedSize(self.size())
        self.playBar.resize(self.width(), self.playBar.height())
        self.songListWidget.resize(self.width(), self.height() - 382)
        self.smallestModeInterface.resize(self.size())
        if self.isPlaylistVisible:
            self.playBar.move(0, 190)
            self.songListWidget.move(0, 382)
            self.songInfoCardChute.move(0, 258 - self.height())
        else:
            self.playBar.move(0, self.height() - self.playBar.height())
            self.songListWidget.move(0, self.height())

    def showPlayBar(self):
        """ 显示播放栏 """
        # 只在播放栏不可见的时候显示播放栏和开启动画
        if not self.playBar.isVisible():
            self.playBar.show()
            self.songInfoCardChuteAni.setDuration(450)
            self.songInfoCardChuteAni.setEasingCurve(QEasingCurve.OutCubic)
            self.songInfoCardChuteAni.setStartValue(
                self.songInfoCardChute.rect())
            self.songInfoCardChuteAni.setEndValue(
                QRect(0, -self.playBar.height() + 68, self.width(),
                      self.height()))
            self.songInfoCardChuteAni.start()

    def hidePlayBar(self):
        """ 隐藏播放栏 """
        if self.playBar.isVisible() and not self.isPlaylistVisible:
            self.playBar.hide()
            self.songInfoCardChuteAni.setEasingCurve(QEasingCurve.OutCirc)
            self.songInfoCardChuteAni.setStartValue(
                QRect(0, -self.playBar.height() + 68, self.width(),
                      self.height()))
            self.songInfoCardChuteAni.setEndValue(
                QRect(0, 0, self.width(), self.height()))
            self.songInfoCardChuteAni.start()

    def showPlaylist(self):
        """ 显示播放列表 """
        if self.songListWidgetAni.state() != QAbstractAnimation.Running:
            self.songInfoCardChuteAni.setDuration(350)
            self.songInfoCardChuteAni.setEasingCurve(QEasingCurve.InOutQuad)
            self.songInfoCardChuteAni.setStartValue(
                QRect(0, self.songInfoCardChute.y(), self.width(),
                      self.height()))
            self.songInfoCardChuteAni.setEndValue(
                QRect(0, 258 - self.height(), self.width(), self.height()))
            self.playBarAni.setStartValue(
                QRect(0, self.playBar.y(), self.width(),
                      self.playBar.height()))
            self.playBarAni.setEndValue(
                QRect(0, 190, self.width(), self.playBar.height()))
            self.songListWidgetAni.setStartValue(
                QRect(
                    self.songListWidget.x(),
                    self.songListWidget.y(),
                    self.songListWidget.width(),
                    self.songListWidget.height(),
                ))
            self.songListWidgetAni.setEndValue(
                QRect(
                    self.songListWidget.x(),
                    382,
                    self.songListWidget.width(),
                    self.songListWidget.height(),
                ))
            if self.sender() == self.playBar.showPlaylistButton:
                self.playBar.pullUpArrowButton.timer.start()
            self.playBar.show()
            self.parallelAniGroup.start()
            self.blurBackgroundPic.hide()
            self.showPlaylistTimer.start()

    def showPlayListTimerSlot(self):
        """ 显示播放列表定时器溢出槽函数 """
        self.showPlaylistTimer.stop()
        self.songListWidgetAni.start()
        self.isPlaylistVisible = True

    def hidePlayListTimerSlot(self):
        """ 显示播放列表定时器溢出槽函数 """
        self.hidePlaylistTimer.stop()
        self.parallelAniGroup.start()

    def hidePlaylist(self):
        """ 隐藏播放列表 """
        if self.parallelAniGroup.state() != QAbstractAnimation.Running:
            self.songInfoCardChuteAni.setDuration(350)
            self.songInfoCardChuteAni.setEasingCurve(QEasingCurve.InOutQuad)
            self.songInfoCardChuteAni.setStartValue(
                QRect(0, self.songInfoCardChute.y(), self.width(),
                      self.height()))
            self.songInfoCardChuteAni.setEndValue(
                QRect(0, -self.playBar.height() + 68, self.width(),
                      self.height()))
            self.playBarAni.setStartValue(
                QRect(0, 190, self.width(), self.playBar.height()))
            self.playBarAni.setEndValue(
                QRect(
                    0,
                    self.height() - self.playBar.height(),
                    self.width(),
                    self.playBar.height(),
                ))
            self.songListWidgetAni.setStartValue(
                QRect(
                    self.songListWidget.x(),
                    self.songListWidget.y(),
                    self.songListWidget.width(),
                    self.songListWidget.height(),
                ))
            self.songListWidgetAni.setEndValue(
                QRect(
                    self.songListWidget.x(),
                    self.height(),
                    self.songListWidget.width(),
                    self.songListWidget.height(),
                ))
            if self.sender() == self.playBar.showPlaylistButton:
                self.playBar.pullUpArrowButton.timer.start()
            # self.parallelAniGroup.start()
            self.songListWidgetAni.start()
            self.hidePlaylistTimer.start()
            self.blurBackgroundPic.show()
            self.isPlaylistVisible = False

    def showPlaylistButtonSlot(self):
        """ 显示或隐藏播放列表 """
        if not self.isPlaylistVisible:
            self.showPlaylist()
        else:
            self.hidePlaylist()

    def setCurrentIndex(self, index):
        """ 更新播放列表下标 """
        # 下标大于等于0时才更新
        if self.currentIndex != index and index > -1:
            # 在播放列表的最后一首歌被移除时不更新样式
            if index >= len(self.playlist):
                return
            if self.smallestModeInterface.isVisible():
                self.smallestModeInterface.setCurrentIndex(index)
            self.currentIndex = index
            self.songListWidget.setCurrentIndex(index)
            self.songInfoCardChute.setCurrentIndex(index)

    def setPlaylist(self, playlist: list, isResetIndex: bool = True):
        """ 更新播放列表

        Parameters
        ----------
        playlist: list
            播放列表,每一个元素都是songInfo字典

        isResetIndex: bool
            是否将下标重置为0
        """
        self.playlist = deepcopy(playlist)
        self.currentIndex = 0 if isResetIndex else self.currentIndex
        if playlist:
            self.songInfoCardChute.setPlaylist(self.playlist, isResetIndex)
            self.smallestModeInterface.setPlaylist(self.playlist, isResetIndex)
            self.songListWidget.updateSongCards(self.playlist)
        # 如果小部件不可见就显示
        if playlist and not self.songListWidget.isVisible():
            self.__setGuideLabelHidden(True)

    def __settleDownPlayBar(self):
        """ 定住播放栏 """
        self.songInfoCardChute.stopSongInfoCardTimer()

    def __startSongInfoCardTimer(self):
        """ 重新打开歌曲信息卡的定时器 """
        if not self.playBar.volumeSlider.isVisible():
            # 只有音量滑动条不可见才打开计时器
            self.songInfoCardChute.startSongInfoCardTimer()

    def __songListWidgetCurrentChangedSlot(self, index):
        """ 歌曲列表当前下标改变插槽 """
        self.currentIndex = index
        self.songInfoCardChute.setCurrentIndex(index)
        self.currentIndexChanged.emit(index)

    def __songInfoCardChuteCurrentChangedSlot(self, index):
        """ 歌曲列表当前下标改变插槽 """
        self.currentIndex = index
        self.songListWidget.setCurrentIndex(index)
        self.currentIndexChanged.emit(index)

    def __removeSongFromPlaylist(self, index):
        """ 从播放列表中移除选中的歌曲 """
        lastSongRemoved = False
        if self.currentIndex > index:
            self.currentIndex -= 1
            self.songInfoCardChute.currentIndex -= 1
        elif self.currentIndex == index:
            # 如果被移除的是最后一首需要将当前下标-1
            if index == self.songListWidget.currentIndex + 1:
                self.currentIndex -= 1
                self.songInfoCardChute.currentIndex -= 1
                lastSongRemoved = True
            else:
                self.songInfoCardChute.setCurrentIndex(self.currentIndex)
        self.removeMediaSignal.emit(index)
        # 如果播放列表为空,隐藏小部件
        if len(self.playlist) == 0:
            self.__setGuideLabelHidden(False)
        # 如果被移除的是最后一首就将当前播放歌曲置为被移除后的播放列表最后一首
        """ if lastSongRemoved:
            self.currentIndexChanged.emit(self.currentIndex) """

    def clearPlaylist(self):
        """ 清空歌曲卡 """
        self.playlist.clear()
        self.songListWidget.clearSongCards()
        # 显示随机播放所有按钮
        self.__setGuideLabelHidden(False)

    def __setGuideLabelHidden(self, isHidden):
        """ 设置导航标签和随机播放所有按钮的可见性 """
        self.randomPlayAllButton.setHidden(isHidden)
        self.guideLabel.setHidden(isHidden)
        self.songListWidget.setHidden(not isHidden)
        if isHidden:
            # 隐藏导航标签时根据播放列表是否可见设置磨砂背景和播放栏的可见性
            self.blurBackgroundPic.setHidden(self.isPlaylistVisible)
            self.playBar.setHidden(not self.isPlaylistVisible)
        else:
            # 显示导航标签时隐藏磨砂背景
            self.blurBackgroundPic.hide()
            self.playBar.hide()
        # 最后再显示歌曲信息卡
        self.songInfoCardChute.setHidden(not isHidden)

    def updateOneSongCard(self, oldSongInfo: dict, newSongInfo):
        """ 更新一个歌曲卡 """
        self.songListWidget.updateOneSongCard(oldSongInfo, newSongInfo)
        self.playlist = self.songListWidget.playlist
        self.songInfoCardChute.playlist = self.playlist

    def updateMultiSongCards(self, oldSongInfo_list: list,
                             newSongInfo_list: list):
        """ 更新多个歌曲卡 """
        self.songListWidget.updateMultiSongCards(oldSongInfo_list,
                                                 newSongInfo_list)
        self.playlist = self.songListWidget.playlist
        self.songInfoCardChute.playlist = self.playlist

    def showSmallestModeInterface(self):
        """ 显示最小播放模式界面 """
        self.exitFullScreenSig.emit()
        # 记录下正常尺寸
        self.currentGeometry = self.window().geometry()  # type:QRect
        # 更新磨砂半径
        self.blurCoverThread.setTargetCover(
            self.blurCoverThread.albumCoverPath, 40, (350, 350))
        self.blurCoverThread.start()
        self.playBar.hide()
        self.songListWidget.hide()
        self.songInfoCardChute.hide()
        self.blurBackgroundPic.show()
        # 先更新歌曲信息卡再显示界面
        self.smallestModeInterface.setCurrentIndex(self.currentIndex)
        self.smallestModeInterface.show()
        # 发出隐藏标题栏按钮的信号
        self.smallestModeStateChanged.emit(True)
        self.window().setMinimumSize(206, 197)
        self.window().setGeometry(
            self.currentGeometry.x() + self.currentGeometry.width() -
            self.currentSmallestModeSize.width(),
            self.currentGeometry.y(),
            self.currentSmallestModeSize.width(),
            self.currentSmallestModeSize.height(),
        )

    def __hideSmallestModeInterface(self):
        """ 隐藏最小播放模式界面 """
        # 记录下最小播放模式的尺寸
        self.currentSmallestModeSize = self.window().size()  # type:QSize
        # 更新磨砂半径
        self.blurCoverThread.setTargetCover(
            self.blurCoverThread.albumCoverPath, 6, (450, 450))
        self.blurCoverThread.start()
        self.smallestModeInterface.hide()
        self.window().setMinimumSize(1030, 850)
        self.window().setGeometry(self.currentGeometry)
        # 发出显示标题栏按钮的信号
        self.smallestModeStateChanged.emit(False)
        self.blurBackgroundPic.setHidden(self.isPlaylistVisible)
        self.playBar.show()
        self.songListWidget.show()
        self.songInfoCardChute.show()

    def __connectSignalToSlot(self):
        """ 将信号连接到槽 """
        self.blurCoverThread.blurDone.connect(self.setBlurPixmap)
        # 更新背景封面和下标
        self.songInfoCardChute.currentIndexChanged[int].connect(
            self.__songInfoCardChuteCurrentChangedSlot)
        self.songInfoCardChute.currentIndexChanged[str].connect(
            self.startBlurThread)
        # 显示和隐藏播放栏
        self.songInfoCardChute.showPlayBarSignal.connect(self.showPlayBar)
        self.songInfoCardChute.hidePlayBarSignal.connect(self.hidePlayBar)
        # 将播放栏的信号连接到槽
        self.playBar.lastSongButton.clicked.connect(self.lastSongSig)
        self.playBar.nextSongButton.clicked.connect(self.nextSongSig)
        self.playBar.playButton.clicked.connect(self.switchPlayStateSig)
        self.playBar.pullUpArrowButton.clicked.connect(
            self.showPlaylistButtonSlot)
        self.playBar.showPlaylistButton.clicked.connect(
            self.showPlaylistButtonSlot)
        self.playBar.smallPlayModeButton.clicked.connect(
            self.showSmallestModeInterface)
        self.playBar.enterSignal.connect(self.__settleDownPlayBar)
        self.playBar.leaveSignal.connect(self.__startSongInfoCardTimer)
        # 将歌曲列表的信号连接到槽函数
        self.songListWidget.currentIndexChanged.connect(
            self.__songListWidgetCurrentChangedSlot)
        self.songListWidget.removeItemSignal.connect(
            self.__removeSongFromPlaylist)
        self.randomPlayAllButton.clicked.connect(self.randomPlayAllSignal)
        # 将最小化播放界面的信号连接到槽函数
        self.smallestModeInterface.lastSongButton.clicked.connect(
            self.lastSongSig)
        self.smallestModeInterface.nextSongButton.clicked.connect(
            self.nextSongSig)
        self.smallestModeInterface.playButton.clicked.connect(
            self.switchPlayStateSig)
        self.smallestModeInterface.exitSmallestModeButton.clicked.connect(
            self.__hideSmallestModeInterface)
        # 切换到专辑界面
        self.songInfoCardChute.switchToAlbumInterfaceSig.connect(
            self.switchToAlbumInterfaceSig)
        self.songListWidget.switchToAlbumInterfaceSig.connect(
            self.switchToAlbumInterfaceSig)
예제 #7
0
class SubPlayWindow(QWidget):
    """ 桌面左上角子播放窗口 """
    def __init__(self, parent=None, songInfo: dict = None):
        super().__init__(parent)
        self.songInfo = {}
        if songInfo:
            self.songInfo = songInfo
        self.__lastSongIconPath = {
            'normal':
            r'resource\images\sub_play_window\lastSong_50_50_normal.png',
            'hover':
            r'resource\images\sub_play_window\lastSong_50_50_hover.png',
            'pressed':
            r'resource\images\sub_play_window\lastSong_50_50_pressed.png'
        }
        self.__nextSongIconPath = {
            'normal':
            r'resource\images\sub_play_window\nextSong_50_50_normal.png',
            'hover':
            r'resource\images\sub_play_window\nextSong_50_50_hover.png',
            'pressed':
            r'resource\images\sub_play_window\nextSong_50_50_pressed.png'
        }
        # 创建小部件
        self.volumeSlider = Slider(Qt.Vertical, self)
        self.volumeLabel = QLabel(self)
        self.lastSongButton = ThreeStateButton(self.__lastSongIconPath, self,
                                               (50, 50))
        self.playButton = PlayButton(self)
        self.nextSongButton = ThreeStateButton(self.__nextSongIconPath, self,
                                               (50, 50))
        self.albumPic = QLabel(self)
        self.songNameLabel = QLabel(self)
        self.songerNameLabel = QLabel(self)
        self.ani = QPropertyAnimation(self, b'windowOpacity')
        self.timer = QTimer(self)
        # 系统音量控制类
        self.systemVolume = SystemVolume()
        # 初始化
        self.__initWidget()

    def __initWidget(self):
        """ 初始化小部件 """
        self.resize(635, 175)
        self.__initLayout()
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.Window
                            | Qt.WindowStaysOnTopHint)
        # 初始化音量滑块
        self.volumeSlider.setRange(0, 100)
        self.volumeSlider.setSingleStep(1)
        # 初始化动画和定时器
        self.timer.setInterval(3000)
        self.ani.setEasingCurve(QEasingCurve.Linear)
        self.ani.setDuration(700)
        self.ani.setStartValue(1)
        self.ani.setEndValue(0)
        # 分配ID
        self.volumeLabel.setObjectName('volumeLabel')
        self.songNameLabel.setObjectName('songNameLabel')
        self.songerNameLabel.setObjectName('songerNameLabel')
        # 设置层叠样式
        self.__setQss()
        # 将信号连接到槽
        self.__connectSignalToSlot()
        self.volumeSlider.setValue(self.systemVolume.getVolume())
        # 设置封面和标签
        self.updateWindow(self.songInfo)
        # 引用方法
        self.setPlay = self.playButton.setPlay

    def __initLayout(self):
        """ 初始化布局 """
        self.move(62, 75)
        self.albumPic.move(478, 25)
        self.playButton.move(222, 26)
        self.volumeLabel.move(32, 140)
        self.volumeSlider.move(34, 25)
        self.songNameLabel.move(122, 93)
        self.lastSongButton.move(122, 26)
        self.nextSongButton.move(322, 26)
        self.songerNameLabel.move(122, 135)
        self.albumPic.setFixedSize(125, 125)
        self.songNameLabel.setFixedWidth(285)
        self.songerNameLabel.setFixedWidth(290)
        self.volumeLabel.setFixedWidth(65)

    def updateWindow(self, songInfo: dict):
        """ 设置窗口内容 """
        self.songInfo = songInfo
        self.songName = self.songInfo.get('songName', '未知歌曲')
        self.songerName = self.songInfo.get('songer', '未知歌手')
        # 调整长度
        self.__adjustText()
        # 更新标签和专辑封面
        self.songNameLabel.setText(self.songName)
        self.songerNameLabel.setText(self.songerName)
        self.__setAlbumCover()

    def timerSlot(self):
        """ 定时器溢出时间 """
        self.timer.stop()
        self.ani.start()

    def enterEvent(self, e):
        """ 鼠标进入时停止动画并重置定时器 """
        self.timer.stop()
        if self.ani.state() == QAbstractAnimation.Running:
            self.ani.stop()
            self.setWindowOpacity(1)

    def leaveEvent(self, e):
        """ 鼠标离开窗口时打开计时器 """
        # 判断事件发生的位置发生在自己所占的rect内
        notLeave = isNotLeave(self)
        if not notLeave:
            self.timer.start()

    def show(self):
        """ show()时重置透明度并根据鼠标位置决定是否打开计时器 """
        self.setWindowOpacity(1)
        self.volumeSlider.setValue(self.systemVolume.getVolume())
        super().show()
        notLeave = isNotLeave(self)
        if not notLeave:
            self.timer.start()

    def paintEvent(self, e):
        """ 绘制背景色 """
        painter = QPainter(self)
        painter.setRenderHints(QPainter.Antialiasing)
        painter.setPen(Qt.NoPen)
        brush = QBrush(Qt.black)
        painter.setBrush(brush)
        # 绘制音量滑动条的背景
        painter.drawRect(0, 0, 81, 175)
        # 绘制控制面板的背景
        painter.drawRect(86, 0, 549, 175)

    def __connectSignalToSlot(self):
        """ 将信号连接到槽 """
        self.ani.finished.connect(self.hide)
        self.timer.timeout.connect(self.timerSlot)
        self.volumeSlider.valueChanged.connect(self.sliderValueChangedSlot)

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

    def __setAlbumCover(self):
        """ 设置封面 """
        # 如果专辑信息为空就直接隐藏
        self.coverPath = getCoverPath(self.songInfo.get('modifiedAlbum'))
        self.albumPic.setPixmap(
            QPixmap(self.coverPath).scaled(125, 125, Qt.KeepAspectRatio,
                                           Qt.SmoothTransformation))

    def __adjustText(self):
        """ 根据文本长度决定是否显示省略号 """
        fontMetrics_1 = QFontMetrics(QFont('Microsoft YaHei', 17, 63))
        self.songName = fontMetrics_1.elidedText(self.songName, Qt.ElideRight,
                                                 285)
        fontMetrics_2 = QFontMetrics(QFont('Microsoft YaHei', 9))
        self.songerName = fontMetrics_2.elidedText(self.songerName,
                                                   Qt.ElideRight, 290)

    def __adjustVolumeLabelPos(self):
        """ 调整音量标签的位置 """
        if 10 <= int(self.volumeLabel.text()) <= 99:
            self.volumeLabel.move(32, 140)
        elif 0 <= int(self.volumeLabel.text()) <= 9:
            self.volumeLabel.move(37, 140)
        else:
            self.volumeLabel.move(27, 140)

    def sliderValueChangedSlot(self, value):
        """ 音量改变时调整系统音量并更新标签 """
        self.volumeLabel.setText(str(value))
        self.__adjustVolumeLabelPos()
        self.systemVolume.setVolume(value)
예제 #8
0
class QSlideSwitchPrivate(QObject):

    def __init__(self, q):
        QObject.__init__(self)

        self._position = 0
        self._sliderShape = QRectF()
        self._gradient = QLinearGradient()
        self._gradient.setSpread(QGradient.PadSpread)
        self._qPointer = q

        self.animation = QPropertyAnimation(self, b"position")
        self.animation.setTargetObject(self)
        # self.animation.setPropertyName()
        self.animation.setStartValue(0)
        self.animation.setEndValue(1)
        self.animation.setDuration(300)
        self.animation.setEasingCurve(QEasingCurve.InOutExpo)

    def __del__(self):
        del self.animation

    @pyqtProperty(float)
    def position(self):
        return self._position

    @position.setter
    def position(self, value):
        self._position = value
        self._qPointer.repaint()

    def drawSlider(self, painter):
        margin = 3
        r = self._qPointer.rect().adjusted(0, 0, -1, -1)
        dx = (r.width() - self._sliderShape.width()) * self._position
        sliderRect = self._sliderShape.translated(dx, 0)
        painter.setPen(Qt.NoPen)

        # basic settings
        shadow = self._qPointer.palette().color(QPalette.Dark)
        light = self._qPointer.palette().color(QPalette.Light)
        button = self._qPointer.palette().color(QPalette.Button)

        # draw background
        # draw outer background
        self._gradient.setColorAt(0, shadow.darker(130))
        self._gradient.setColorAt(1, light.darker(130))
        self._gradient.setStart(0, r.height())
        self._gradient.setFinalStop(0, 0)
        painter.setBrush(self._gradient)
        painter.drawRoundedRect(r, 15, 15)

        # draw background
        # draw inner background
        self._gradient.setColorAt(0, shadow.darker(140))
        self._gradient.setColorAt(1, light.darker(160))
        self._gradient.setStart(0, 0)
        self._gradient.setFinalStop(0, r.height())
        painter.setBrush(self._gradient)
        painter.drawRoundedRect(r.adjusted(margin, margin, -margin, -margin), 15, 15)

        # draw slider
        self._gradient.setColorAt(0, button.darker(130))
        self._gradient.setColorAt(1, button)

        # draw outer slider
        self._gradient.setStart(0, r.height())
        self._gradient.setFinalStop(0, 0)
        painter.setBrush(self._gradient)
        painter.drawRoundedRect(sliderRect.adjusted(margin, margin, -margin, -margin), 10, 15)

        # draw inner slider
        self._gradient.setStart(0, 0)
        self._gradient.setFinalStop(0, r.height())
        painter.setBrush(self._gradient)
        painter.drawRoundedRect(sliderRect.adjusted(2.5 * margin, 2.5 * margin, -2.5 * margin, - 2.5 * margin), 5, 15)

        # draw text
        if self.animation.state() == QPropertyAnimation.Running:
            return  # don't draw any text while animation is running

        font = self._qPointer.font()
        self._gradient.setColorAt(0, light)
        self._gradient.setColorAt(1, shadow)
        self._gradient.setStart(0, r.height() / 2.0 + font.pointSizeF())
        self._gradient.setFinalStop(0, r.height() / 2.0 - font.pointSizeF())
        painter.setFont(font)
        painter.setPen(QPen(QBrush(self._gradient), 0))

        if self._qPointer.isChecked():
            painter.drawText(0, 0, r.width() / 2, r.height() - 1, Qt.AlignCenter, "ON")
        else:
            painter.drawText(r.width() / 2, 0, r.width() / 2, r.height() - 1, Qt.AlignCenter, "OFF")

    def updateSliderRect(self, size):
        self._sliderShape.setWidth(size.width() / 2.0)
        self._sliderShape.setHeight(size.height() - 1.0)

    @pyqtSlot(bool, name='animate')
    def animate(self, checked):
        self.animation.setDirection(QPropertyAnimation.Forward if checked else QPropertyAnimation.Backward)
        self.animation.start()
예제 #9
0
class Screen(QWidget):
    card_w = 200
    card_h = 250
    card_start_x = SCREEN_X / 2 - card_w / 2
    card_start_y = SCREEN_Y / 2 - card_h / 2
    card_pause_x = SCREEN_X / 2 - card_w / 2
    card_pause_y = 0.4275 * SCREEN_Y - card_h / 2
    card_pause2_x = SCREEN_X / 2 - card_w / 2
    card_pause2_y = 0.4225 * SCREEN_Y - card_h / 2
    card_pause3_x = SCREEN_X / 2 - card_w / 2
    card_pause3_y = 0.4175 * SCREEN_Y - card_h / 2
    card_end_x = SCREEN_X / 2 - card_w / 2
    card_end_y = SCREEN_Y / 6 - card_h / 2
    speed = 1000

    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.initButtons()

        self.printerback = QLabel(self)
        self.printerback.setStyleSheet(
            "QLabel {border-image: url(./images/printer-back.png) 0 0 0 0 stretch stretch}"
        )
        self.printerback.setGeometry(
            QRect(SCREEN_X / 2 - SCREEN_X / 4.2,
                  SCREEN_Y / 2 - SCREEN_Y / 2.625, SCREEN_X / 2.1,
                  SCREEN_Y / 1.3125))
        self.label = PrintCard(self, self.card_start_x, self.card_start_y,
                               self.card_w, self.card_h)
        self.label.setText(self.chooseWord())
        self.printerfront = QLabel(self)
        self.printerfront.setStyleSheet(
            "QLabel {border-image: url(./images/printer-front.png) 0 0 0 0 stretch stretch}"
        )
        self.printerfront.setGeometry(
            QRect(SCREEN_X / 2 - SCREEN_X / 4.2,
                  SCREEN_Y / 2 - SCREEN_Y / 2.625, SCREEN_X / 2.1,
                  SCREEN_Y / 1.3125))

        self.gameover = QLabel(self)
        self.gameover.setVisible(False)
        self.gameover.setText("Game Over!")
        self.gameover.setStyleSheet("font-size: 30pt")
        self.gameover.setGeometry(
            QRect(SCREEN_X / 6 - SCREEN_X / 16.8, SCREEN_Y / 2, SCREEN_X / 8.4,
                  SCREEN_Y / 25))

        self.anim = QPropertyAnimation(self.label, b"geometry")
        self.anim.setDuration(self.speed)
        self.anim.setStartValue(
            QRect(self.label.x(), self.label.y(), self.label.card_w,
                  self.label.card_h))
        self.anim.setEndValue(
            QRect(self.card_pause_x, self.card_pause_y, self.label.card_w,
                  self.label.card_h))

        self.anim2 = QPropertyAnimation(self.label, b"geometry")
        self.anim2.setDuration(200)
        self.anim2.setEndValue(
            QRect(self.card_pause2_x, self.card_pause2_y, self.label.card_w,
                  self.label.card_h))

        self.anim3 = QPropertyAnimation(self.label, b"geometry")
        self.anim3.setDuration(200)
        self.anim3.setEndValue(
            QRect(self.card_pause3_x, self.card_pause3_y, self.label.card_w,
                  self.label.card_h))

        self.animFinish = QPropertyAnimation(self.label, b"geometry")
        self.animFinish.setDuration(self.speed)
        self.animFinish.setEndValue(
            QRect(self.card_end_x, self.card_end_y, self.label.card_w,
                  self.label.card_h))

        self.startbutton.clicked.connect(self.startButtonClicked)
        self.randombutton.clicked.connect(self.randomButtonClicked)
        self.printbutton.clicked.connect(self.printButtonClicked)
        self.print2button.clicked.connect(self.print2ButtonClicked)
        self.print3button.clicked.connect(self.print3ButtonClicked)
        self.finishprintbutton.clicked.connect(self.finishprintButtonClicked)
        self.reprintbutton.clicked.connect(self.reprintButtonClicked)
        self.nextbutton.clicked.connect(self.nextButtonClicked)
        self.restartbutton.clicked.connect(self.restartButtonClicked)
        self.exitbutton.clicked.connect(self.exit)
        self.animFinish.finished.connect(self.endAnimation)

        self.setWindowTitle("Printer")
        self.setGeometry(0, 0, SCREEN_X, SCREEN_Y)
        self.show()

    def initButtons(self):
        self.startbutton = PrinterButton("Start",
                                         self,
                                         width=SCREEN_X / 8.4,
                                         height=SCREEN_Y / 25,
                                         xPos=SCREEN_X / 6 - SCREEN_X / 16.8,
                                         yPos=SCREEN_Y / 2,
                                         font_size="20pt",
                                         background_color="#77eb34",
                                         background_color_pressed="#449615",
                                         border_radius="8px")

        self.randombutton = PrinterButton("Randomize Words",
                                          self,
                                          width=SCREEN_X / 8.4,
                                          height=SCREEN_Y / 25,
                                          xPos=SCREEN_X / 6 - SCREEN_X / 16.8,
                                          yPos=SCREEN_Y / 2 - SCREEN_Y / 25 -
                                          15,
                                          font_size="20pt",
                                          background_color="#f49eff",
                                          background_color_pressed="#a843cc",
                                          border_radius="8px")

        self.printbutton = PrinterButton("Print",
                                         self,
                                         visible=False,
                                         width=SCREEN_X / 8.4,
                                         height=SCREEN_Y / 25,
                                         xPos=SCREEN_X / 6 - SCREEN_X / 16.8,
                                         yPos=SCREEN_Y / 2,
                                         font_size="20pt",
                                         background_color="#77eb34",
                                         background_color_pressed="#449615",
                                         border_radius="8px")

        self.print2button = PrinterButton("Print More",
                                          self,
                                          visible=False,
                                          width=SCREEN_X / 8.4,
                                          height=SCREEN_Y / 25,
                                          xPos=SCREEN_X / 6 - SCREEN_X / 16.8,
                                          yPos=SCREEN_Y / 2 + SCREEN_Y / 25 +
                                          15,
                                          font_size="20pt",
                                          background_color="#77eb34",
                                          background_color_pressed="#449615",
                                          border_radius="8px")

        self.print3button = PrinterButton("Print More",
                                          self,
                                          visible=False,
                                          width=SCREEN_X / 8.4,
                                          height=SCREEN_Y / 25,
                                          xPos=SCREEN_X / 6 - SCREEN_X / 16.8,
                                          yPos=SCREEN_Y / 2 + SCREEN_Y / 25 +
                                          15,
                                          font_size="20pt",
                                          background_color="#77eb34",
                                          background_color_pressed="#449615",
                                          border_radius="8px")

        self.finishprintbutton = PrinterButton(
            "Finish Printing",
            self,
            visible=False,
            width=SCREEN_X / 8.4,
            height=SCREEN_Y / 25,
            xPos=SCREEN_X / 6 - SCREEN_X / 16.8,
            yPos=SCREEN_Y / 2,
            font_size="20pt",
            background_color="#ff9717",
            background_color_pressed="#8f4f00",
            border_radius="8px")

        self.reprintbutton = PrinterButton("Print Again",
                                           self,
                                           visible=False,
                                           width=SCREEN_X / 8.4,
                                           height=SCREEN_Y / 25,
                                           xPos=SCREEN_X / 6 - SCREEN_X / 16.8,
                                           yPos=SCREEN_Y / 2 + SCREEN_Y / 25 +
                                           15,
                                           font_size="20pt",
                                           background_color="#77eb34",
                                           background_color_pressed="#449615",
                                           border_radius="8px")

        self.nextbutton = PrinterButton("Next Page",
                                        self,
                                        visible=False,
                                        width=SCREEN_X / 8.4,
                                        height=SCREEN_Y / 25,
                                        xPos=SCREEN_X / 6 - SCREEN_X / 16.8,
                                        yPos=SCREEN_Y / 2,
                                        font_size="20pt",
                                        background_color="#f49eff",
                                        background_color_pressed="#a843cc",
                                        border_radius="8px")

        self.restartbutton = PrinterButton("Restart",
                                           self,
                                           visible=False,
                                           width=SCREEN_X / 8.4,
                                           height=SCREEN_Y / 25,
                                           xPos=SCREEN_X / 6 - SCREEN_X / 16.8,
                                           yPos=SCREEN_Y / 2 - SCREEN_Y / 25 -
                                           15,
                                           font_size="20pt",
                                           background_color="#30f5ff",
                                           background_color_pressed="17a6ff",
                                           border_radius="8px")

        self.exitbutton = PrinterButton("Exit",
                                        self,
                                        width=SCREEN_X / 8.4,
                                        height=SCREEN_Y / 25,
                                        xPos=SCREEN_X / 6 - SCREEN_X / 16.8,
                                        yPos=8 * SCREEN_Y / 10 - SCREEN_Y / 50,
                                        font_size="20pt",
                                        background_color="#fc3003",
                                        background_color_pressed="a11216",
                                        border_radius="8px")

    def startButtonClicked(self):
        self.startbutton.setVisible(False)
        self.randombutton.setVisible(False)
        self.printbutton.setVisible(True)
        self.restartbutton.setVisible(True)

    def randomButtonClicked(self):
        global WORDS
        WORDS = read_words.shuffle(WORDS)
        self.restartButtonClicked()

    def printButtonClicked(self):
        self.anim.start()
        self.printbutton.setVisible(False)
        self.print2button.setVisible(True)
        self.finishprintbutton.setVisible(True)

    def print2ButtonClicked(self):
        if self.anim.state() == 2:
            return
        self.anim2.setStartValue(
            QRect(self.label.x(), self.label.y(), self.label.card_w,
                  self.label.card_h))
        self.anim2.start()
        self.print2button.setVisible(False)
        self.print3button.setVisible(True)

    def print3ButtonClicked(self):
        if self.anim2.state() == 2:
            return
        self.anim3.setStartValue(
            QRect(self.label.x(), self.label.y(), self.label.card_w,
                  self.label.card_h))
        self.anim3.start()
        self.print3button.setVisible(False)

    def finishprintButtonClicked(self):
        if (self.anim.state() == 2 or self.anim2.state() == 2
                or self.anim3.state() == 2):
            return
        self.animFinish.setStartValue(
            QRect(self.label.x(), self.label.y(), self.label.card_w,
                  self.label.card_h))
        self.animFinish.start()
        self.printbutton.setVisible(False)
        self.print2button.setVisible(False)
        self.print3button.setVisible(False)
        self.finishprintbutton.setVisible(False)
        self.nextbutton.setVisible(True)
        self.reprintbutton.setVisible(True)

    def reprintButtonClicked(self):
        if self.animFinish.state() == 2:
            return
        global INDEX
        INDEX -= 1
        self.nextButtonClicked()

    def nextButtonClicked(self):
        if self.animFinish.state() == 2:
            return
        if INDEX >= len(WORDS):
            self.restartbutton.setVisible(True)
            self.reprintbutton.setVisible(False)
            self.nextbutton.setVisible(False)
            self.gameover.setVisible(True)
            return
        self.resetUI()

    def restartButtonClicked(self):
        if self.anim.state() == 2:
            return
        global INDEX
        INDEX = 0
        self.resetUI(main_menu=True)

    def endAnimation(self):
        self.printbutton.setVisible(False)
        self.finishprintbutton.setVisible(False)
        self.nextbutton.setVisible(True)
        self.reprintbutton.setVisible(True)

    def chooseWord(self):
        global INDEX
        word = WORDS[INDEX]
        INDEX += 1
        return word

    def resetUI(self, main_menu=False):
        if main_menu:
            self.startbutton.setVisible(True)
            self.randombutton.setVisible(True)
            self.printbutton.setVisible(False)
            self.restartbutton.setVisible(False)
        else:
            self.startbutton.setVisible(False)
            self.randombutton.setVisible(False)
            self.printbutton.setVisible(True)
            self.restartbutton.setVisible(True)
        self.gameover.setVisible(False)
        self.anim.setCurrentTime(0)
        self.animFinish.setCurrentTime(0)
        self.reprintbutton.setVisible(False)
        self.nextbutton.setVisible(False)
        self.label.setText(self.chooseWord())
        self.label.move(self.card_start_x, self.card_start_y)

    def exit(self):
        sys.exit(0)
예제 #10
0
class SideSlideAnimator(AbstractAnimator):
    m_side: ApplicationSide
    m_decorateBackground: bool
    m_decorator: SideSlideDecorator
    m_animation: QPropertyAnimation

    def __init__(self, _widgetForSlide):
        super(SideSlideAnimator, self).__init__(_widgetForSlide)

        self.m_side = ApplicationSide()
        self.m_decorateBackground = True
        self.m_decorator = SideSlideDecorator(_widgetForSlide.parentWidget())
        self.m_animation = QPropertyAnimation(self.m_decorator, b"_slidePos")

        _widgetForSlide.parentWidget().installEventFilter(self)

        self.m_animation.setEasingCurve(QEasingCurve.InQuad)
        self.m_animation.setDuration(260)

        self.m_decorator.hide()

        def finished():
            self.setAnimatedStopped()
            if self.isAnimatedForward():
                self.widgetForSlide().move(self.m_decorator.slidePos())
            else:
                self.m_decorator.hide()

        self.m_animation.finished.connect(finished)

        self.m_decorator.clicked.connect(self.slideOut)

    def setApplicationSide(self, _side):
        if self.m_side != _side:
            self.m_side = _side

    def setDecorateBackground(self, _decorate):
        if self.m_decorateBackground != _decorate:
            self.m_decorateBackground = _decorate

    def animationDuration(self):
        return self.m_animation.duration()

    def animateForward(self):
        self.slideIn()

    def slideIn(self):
        if self.isAnimated() and self.isAnimatedForward():
            return
        self.setAnimatedForward()

        self.widgetForSlide().lower()
        self.widgetForSlide().move(-self.widgetForSlide().width(),
                                   -self.widgetForSlide().height())
        self.widgetForSlide().show()
        self.widgetForSlide().resize(self.widgetForSlide().sizeHint())

        _topWidget = self.widgetForSlide()
        topWidget = self.widgetForSlide()
        while _topWidget:
            topWidget = _topWidget
            _topWidget = topWidget.parentWidget()

        finalSize = self.widgetForSlide().size()
        startPosition = QPoint()
        finalPosition = QPoint()
        if self.m_side == ApplicationSide.LeftSide:
            finalSize.setHeight(topWidget.height())
            startPosition = QPoint(-finalSize.width(), 0)
            finalPosition = QPoint(0, 0)
        if self.m_side == ApplicationSide.TopSide:
            finalSize.setWidth(topWidget.width())
            startPosition = QPoint(0, -finalSize.height())
            finalPosition = QPoint(0, 0)
        if self.m_side == ApplicationSide.RightSide:
            finalSize.setHeight(topWidget.height())
            startPosition = QPoint(topWidget.width(), 0)
            finalPosition = QPoint(topWidget.width() - finalSize.width(), 0)
        if self.m_side == ApplicationSide.BottomSide:
            finalSize.setWidth(topWidget.width())
            startPosition = QPoint(0, topWidget.height())
            finalPosition = QPoint(0, topWidget.height() - finalSize.height())

        if self.m_decorateBackground:
            self.m_decorator.setParent(topWidget)
            self.m_decorator.move(0, 0)
            self.m_decorator.grabParent()
            self.m_decorator.show()
            self.m_decorator.raise_()

        self.widgetForSlide().move(startPosition)
        self.widgetForSlide().resize(finalSize)
        self.widgetForSlide().raise_()

        self.m_decorator.grabSlideWidget(self.widgetForSlide())

        if self.m_animation.state() == QPropertyAnimation.Running:
            self.m_animation.pause()
            self.m_animation.setDirection(QPropertyAnimation.Backward)
            self.m_animation.resume()
        else:
            self.m_animation.setEasingCurve(QEasingCurve.OutQuart)
            self.m_animation.setDirection(QPropertyAnimation.Forward)
            self.m_animation.setStartValue(startPosition)
            self.m_animation.setEndValue(finalPosition)
            self.m_animation.start()

        if self.m_decorateBackground:
            DARKER = True
            self.m_decorator.decorate(DARKER)

    def animateBackward(self):
        self.slideOut()

    def slideOut(self):
        if self.isAnimated() and self.isAnimatedBackward():
            return
        self.setAnimatedBackward()

        if self.widgetForSlide().isVisible():
            _topWidget = self.widgetForSlide()
            topWidget = self.widgetForSlide()
            while _topWidget:
                topWidget = _topWidget
                _topWidget = topWidget.parentWidget()

            self.widgetForSlide().hide()

            finalSize = self.widgetForSlide().size()
            startPosition = self.widgetForSlide().pos()
            finalPosition = QPoint()
            if self.m_side == ApplicationSide.LeftSide:
                startPosition = QPoint(0, 0)
                finalPosition = QPoint(-finalSize.width(), 0)
            if self.m_side == ApplicationSide.TopSide:
                startPosition = QPoint(0, 0)
                finalPosition = QPoint(0, -finalSize.height())
            if self.m_side == ApplicationSide.RightSide:
                startPosition = QPoint(topWidget.width() - finalSize.width(),
                                       0)
                finalPosition = QPoint(topWidget.width(), 0)
            if self.m_side == ApplicationSide.BottomSide:
                startPosition = QPoint(0,
                                       topWidget.height() - finalSize.height())
                finalPosition = QPoint(0, topWidget.height())

            if self.m_animation.state() == QPropertyAnimation.Running:
                self.m_animation.pause()
                self.m_animation.setDirection(QPropertyAnimation.Backward)
                self.m_animation.resume()
            else:
                self.m_animation.setEasingCurve(QEasingCurve.InQuart)
                self.m_animation.setDirection(QPropertyAnimation.Forward)
                self.m_animation.setStartValue(startPosition)
                self.m_animation.setEndValue(finalPosition)
                self.m_animation.start()

            if self.m_decorateBackground:
                LIGHTER = False
                self.m_decorator.decorate(LIGHTER)

    def eventFilter(self, _object, _event):
        if _object == self.widgetForSlide().parentWidget() and _event.type(
        ) == QEvent.Resize:
            widgetForSlideParent = self.widgetForSlide().parentWidget()
            if self.m_side == ApplicationSide.RightSide:
                self.widgetForSlide().move(
                    widgetForSlideParent.width() -
                    self.widgetForSlide().width(), 0)
            if self.m_side == ApplicationSide.LeftSide:
                self.widgetForSlide().resize(self.widgetForSlide().width(),
                                             widgetForSlideParent.height())
            if self.m_side == ApplicationSide.BottomSide:
                self.widgetForSlide().move(
                    0,
                    widgetForSlideParent.height() -
                    self.widgetForSlide().height())
            if self.m_side == ApplicationSide.TopSide:
                self.widgetForSlide().resize(widgetForSlideParent.width(),
                                             self.widgetForSlide().height())

            self.m_decorator.grabSlideWidget(self.widgetForSlide())

        return QObject.eventFilter(self, _object, _event)

    def widgetForSlide(self):
        return self.parent()
예제 #11
0
class SlideAnimator(AbstractAnimator):
    m_direction:AnimationDirection
    m_isFixBackground:bool
    m_isFixStartSize:bool
    m_startMinSize = QSize()
    m_startMaxSize = QSize()
    m_startSize = QSize()
    m_decorator: SlideForegroundDecorator
    m_animation: QPropertyAnimation

    def __init__(self, _widgetForSlide):
        super(SlideAnimator, self).__init__(_widgetForSlide)

        self.m_direction = AnimationDirection.FromLeftToRight
        self.m_isFixBackground = True
        self.m_isFixStartSize = False
        self.m_decorator = SlideForegroundDecorator(_widgetForSlide)
        self.m_animation = QPropertyAnimation(self.m_decorator, b"maximumWidth")

        _widgetForSlide.installEventFilter(self)

        self.m_animation.setDuration(300)

        self.m_decorator.hide()

        def valueChanged(_value):
            if self.isWidth():
                self.widgetForSlide().setMaximumWidth(_value)
            else:
                self.widgetForSlide().setMaximumHeight(_value)
        self.m_animation.valueChanged.connect(valueChanged)

        def finished():
            self.setAnimatedStopped()
            self.m_decorator.hide()
        self.m_animation.finished.connect(finished)

    def setAnimationDirection(self, _direction):
        if self.m_direction != _direction:
            self.m_direction = _direction
        self.m_animation.setPropertyName(b"maximumWidth" if self.isWidth() else b"maximumHeight")

    def setFixBackground(self, _fix):
        if self.m_isFixBackground != _fix:
            self.m_isFixBackground = _fix

    def setFixStartSize(self, _fix):
        if self.m_isFixStartSize != _fix:
            self.m_isFixStartSize = _fix

    def animationDuration(self):
        return self.m_animation.duration()

    def animateForward(self):
        self.slideIn()

    def slideIn(self):
        if not self.m_startMinSize.isValid():
            self.m_startMinSize = self.widgetForSlide().minimumSize()
        if not self.m_startMaxSize.isValid():
            self.m_startMaxSize = self.widgetForSlide().maximumSize()
        if not self.m_startSize.isValid():
            self.m_startSize = self.widgetForSlide().sizeHint()

        if self.isAnimated() and self.isAnimatedForward():
            return
        self.setAnimatedForward()

        if self.isWidth():
            self.widgetForSlide().setMaximumWidth(0)
        else:
            self.widgetForSlide().setMaximumHeight(0)

        self.widgetForSlide().show()
        currentSize = self.widgetForSlide().size()

        finalSize = QSize(currentSize.width(), currentSize.height())
        self.fixSize(self.m_startSize, finalSize)

        self.widgetForSlide().hide()
        self.fixSizeOfWidgetForSlide(finalSize)
        self.m_decorator.grabParent(finalSize)
        self.fixSizeOfWidgetForSlide(currentSize)
        self.widgetForSlide().show()

        if self.m_isFixBackground:
            self.m_decorator.move(0, 0)
            self.m_decorator.show()
            self.m_decorator.raise_()

        if self.m_animation.state() == QPropertyAnimation.Running:
            self.m_animation.pause()
            self.m_animation.setDirection(QPropertyAnimation.Backward)
            self.m_animation.resume()
        else:
            self.m_animation.setEasingCurve(QEasingCurve.OutQuart)
            self.m_animation.setDirection(QPropertyAnimation.Forward)
            self.m_animation.setStartValue(self.widgetForSlide().width() if self.isWidth() else self.widgetForSlide().height())
            self.m_animation.setEndValue(finalSize.width() if self.isWidth() else finalSize.height())
            self.m_animation.start()

    def animateBackward(self):
        self.slideOut()

    def slideOut(self):
        if not self.m_startMinSize.isValid():
            self.m_startMinSize = self.widgetForSlide().minimumSize()
        if not self.m_startMaxSize.isValid():
            self.m_startMaxSize = self.widgetForSlide().maximumSize()
        if not self.m_startSize.isValid() or not self.m_isFixStartSize:
            self.m_startSize = self.widgetForSlide().size()

        if self.isAnimated() and self.isAnimatedBackward():
            return
        self.setAnimatedBackward()

        finalSize = self.widgetForSlide().size()
        if self.isWidth():
            finalSize.setWidth(0)
        else:
            finalSize.setHeight(0)

        self.m_decorator.grabParent(self.widgetForSlide().size())

        if self.m_isFixBackground:
            self.m_decorator.move(0, 0)
            self.m_decorator.show()
            self.m_decorator.raise_()

        if self.m_animation.state() == QPropertyAnimation.Running:
            self.m_animation.pause()
            self.m_animation.setDirection(QPropertyAnimation.Backward)
            self.m_animation.resume()
        else:
            self.m_animation.setEasingCurve(QEasingCurve.InQuart)
            self.m_animation.setDirection(QPropertyAnimation.Forward)
            self.m_animation.setStartValue(self.widgetForSlide().width() if self.isWidth() else self.widgetForSlide().height())
            self.m_animation.setEndValue(finalSize.width() if self.isWidth() else finalSize.height())
            self.m_animation.start()

    def eventFilter(self, _object, _event):
        if _object == self.widgetForSlide() and _event.type() == QEvent.Resize and self.m_decorator.isVisible():
            if self.m_direction == AnimationDirection.FromLeftToRight:
                self.m_decorator.move(self.widgetForSlide().width() - self.m_decorator.width(), 0)
            if self.m_direction == AnimationDirection.FromTopToBottom:
                self.m_decorator.move(0, self.widgetForSlide().height() - self.m_decorator.height())

        return QObject.eventFilter(self, _object, _event)

    def isWidth(self):
        return self.m_direction == AnimationDirection.FromLeftToRight or self.m_direction == AnimationDirection.FromRightToLeft

    def fixSize(self, _sourceSize, _targetSize):
        if self.isWidth():
            _targetSize.setWidth(_sourceSize.width())
        else:
            _targetSize.setHeight(_sourceSize.height())

    def fixSizeOfWidgetForSlide(self, _sourceSize):
        if self.isWidth():
            self.widgetForSlide().setFixedWidth(_sourceSize.width())
        else:
            self.widgetForSlide().setFixedHeight(_sourceSize.height())


    def widgetForSlide(self):
        return self.parent()
예제 #12
0
class LoginWidget(QWidget, Ui_LoginUi):
    DEBUG = 0

    def __init__(self, *args, **kwargs):
        super(LoginWidget, self).__init__(*args, **kwargs)
        self.setupUi(self)
        self.startValue = ''
        self.par = self.parent()
        self.oe = QGraphicsOpacityEffect()

        if os.path.exists('userLogin.ini'):
            with open('userLogin.ini') as f:
                inf = eval(f.read())
                self.lineEdit_2.setText(inf['user'])
                self.lineEdit.setText(inf['pw'])
        else:
            self.lineEdit_2.setText('')
            self.lineEdit.setText('')
        # 初始化爬虫
        self.spider = zk_spider()
        # 定时器
        self.t = QTimer(self)  # 开始的加载背景1
        self.t2 = QTimer(self)  # 使背景1隐藏
        self.t3 = QTimer(self)  # 让背景2浮现
        # 动画
        self.widget_2Ani = QPropertyAnimation(
            self.par.widget_2,
            b"pos",
        )

        # 变量
        self.bgOpacity = 0

        # oe
        self.setGraphicsEffect(self.oe)
        # connect
        self.pushButton.clicked.connect(self.login)
        # 函数

        # 如已有 cookies则直接登录

    def login(self):
        """
        开始判断是否登录成功,若成功,执行动画
        """
        # 获取账号, 密码, 验证码
        user = self.lineEdit_2.text()
        pw = self.lineEdit.text()
        code = self.lineEdit_3.text()
        hot = self.checkBox.checkState()
        auto = self.checkBox_2.checkState()

        if self.DEBUG:
            self.loginAni()
        else:
            if os.path.exists('cookies.c*k'):
                os.remove('cookies.c*k')
            self.spider.checkCookiesAndTryLogin(user, pw, code, False)
            if self.spider.login_success:
                self.loginAni()
            else:
                QMessageBox.warning(self, '用户名或密码 或验证码错误', '用户名或密码 或验证码错误')
        """
        若记住密码
        """
        if self.checkBox.isChecked():
            with open('userLogin.ini', 'w') as f:
                f.write(str({'user': user, 'pw': pw}))
        # 耦合性太强了 麻烦分离 这里开始login了

        pass

    def loginAni(self):

        if not self.widget_2Ani.state():
            self.widget_2Animation()
            self.autoHide()

    def autoHide(self, login=True):
        # 开始切换到content
        if login:
            t = QTimer(self)
            t2 = QTimer(self.par)
            self.par.fadeWidget(
                self.par, t, self.par.widget_2.hide, self.par.widget_2.lower,
                self.par.contentShow,
                lambda: self.par.emergedWidget(self.par.ContentWidget, t2),
                lambda: self.par.setStyleSheet("""
                    QMainWindow#ZhkuMainWindow{
            border-image:url(:/img/img/72e13cfaff5836b02aa0b0553584c7c7.jpg)}
                    """))

        else:
            # 显示login
            # 去除 弹簧
            self.par.removeSpacer(self.par.horizontalLayout_2)
            """
            hide的先后顺序会导致变大变小
            """
            self.par.ContentWidget.hide()

            # 显示 父控件scoretable

    def widget_2Animation(self):
        self.widget_2Ani.setStartValue(
            QPoint(self.par.widget_2.x(), self.par.widget_2.y()))
        self.widget_2Ani.setEndValue(
            QPoint(self.par.widget.x(), self.par.widget.y()))
        self.widget_2Ani.setDuration(3000)
        self.widget_2Ani.setEasingCurve(QEasingCurve.InOutElastic)
        self.widget_2Ani.start()

    def autoLogin(self, login=True):
        """
        自动更换背景
        """

        if login:
            print('尝试自动登录')
            if self.spider.login_success:
                self.loginAni()
        else:
            pass
예제 #13
0
class Button(QGraphicsObject):
    font: QFont = QFont("monospace", 16)

    clicked = pyqtSignal('PyQt_PyObject')
    hovered_ = pyqtSignal('PyQt_PyObject')

    def __init__(self, btn_id: str, label: str, tooltip: str = "", parent: QGraphicsItem = None):
        QGraphicsObject.__init__(self, parent)
        self.setFlag(QGraphicsItem.ItemIgnoresTransformations, True)
        self.scaling = 1.0
        self.label = QGraphicsSimpleTextItem(label, self)
        self.label.setFont(Button.font)
        self.text_color_enabled = QColor(255, 255, 255, 255)
        self.text_color_disabled = QColor(200, 200, 200, 255)
        self.fill_color_disabled = QColor(125, 125, 125, 200)
        self.label.setBrush(QBrush(self.text_color_enabled))
        self.btn_id = btn_id
        self.rect = QRectF(0, 0, 0, 0)

        self.tooltip = QGraphicsSimpleTextItem(tooltip, self)
        self.tooltip.setBrush(QColor(255, 255, 255, 200))
        self.tooltip.setFont(Button.font)
        self.tooltip.setVisible(False)
        self.tooltip.setZValue(25)
        self.tooltip_shown = False

        self.base_color = ButtonColor.GRAY

        self.hor_margin = 10
        self.ver_margin = 5
        self.current_timer = 0

        self.logic: Union[CheckbuttonLogic, PushbuttonLogic] = PushbuttonLogic("gray")
        self.fill_color_current = self.logic.idle_color()

        self.color_animation = QPropertyAnimation(self, b"current_fill_color")
        self.color_animation.setEasingCurve(QEasingCurve.Linear)

        self.hovered = False
        self.setAcceptHoverEvents(True)
        self.setZValue(4)
        self.set_height(12)

        self.pixmap: QPixmap = None
        self.max_pixmap_height = 128
        self.disabled = False

        self.mode = ButtonMode.Button

    def set_height(self, h: int):
        self.prepareGeometryChange()
        self.ver_margin = int(0.25 * h)
        font: QFont = self.label.font()
        font.setPointSize(h)
        self.label.setFont(font)
        self.rect.setWidth(self.label.boundingRect().width() + 2 * self.hor_margin)
        self.rect.setHeight(self.label.boundingRect().height() + 2 * self.ver_margin)
        self._reposition_text()

    def set_width(self, w: int):
        if self.pixmap is not None:
            return
        self.prepareGeometryChange()
        self.rect.setWidth(w)
        self.hor_margin = self.ver_margin
        if self.label.boundingRect().width() > self.rect.width():
            w = self.rect.width() - 2 * self.hor_margin
            factor = w / self.label.boundingRect().width()
            h = factor * self.label.boundingRect().height()
            font = self.label.font()
            font.setPixelSize(max(h, 12))
            self.label.setFont(font)
        self._reposition_text()

    def set_button_height(self, h: int):
        self.rect.setHeight(h)
        self._reposition_text()

    def scale_button(self, factor: float):
        factor = 1.0
        self.rect.setHeight(int(factor * self.rect.height()))
        self.rect.setWidth(int(factor * self.rect.width()))
        self.label.setScale(self.scaling)
        self.fit_to_contents()

    def _reposition_text(self):
        x = self.rect.width() / 2 - self.label.boundingRect().width() / 2
        y = self.rect.height() / 2 - self.label.boundingRect().height() / 2
        self.label.setPos(QPointF(x, y))
        self.update()

    def boundingRect(self):
        return self.rect

    def paint(self, painter: QPainter, options, widget=None):
        painter.setBrush(QBrush(self.fill_color_current))
        painter.setPen(QPen(QColor(0, 0, 0, 0)))

        painter.drawRoundedRect(self.rect, 5, 5)

        if self.pixmap is not None:
            painter.drawPixmap(self.hor_margin * self.scaling, self.ver_margin * self.scaling, self.pixmap)
        if self.tooltip_shown:
            painter.setBrush(QBrush(QColor(50, 50, 50, 200)))
            painter.drawRoundedRect(self.tooltip.boundingRect().translated(self.tooltip.pos())
                                    .marginsAdded(QMarginsF(5, 0, 5, 0)), 5, 5)

    def mousePressEvent(self, event: QGraphicsSceneMouseEvent):
        if self.disabled or self.mode == ButtonMode.Label:
            return
        self.fill_color_current = self.logic.press_color()
        self.scene().update()

    def mouseReleaseEvent(self, event: QGraphicsSceneMouseEvent):
        if self.disabled or self.mode == ButtonMode.Label:
            return
        self.click_button()

    def hoverEnterEvent(self, event: QGraphicsSceneHoverEvent):
        if self.disabled or self.mode == ButtonMode.Label:
            return
        self.hovered_.emit({'btn_id': self.btn_id, 'button': self, 'hovered': True})
        self.hovered = True

        if len(self.tooltip.text()) > 0:
            self.tooltip_shown = True
            self.tooltip.setVisible(True)
            view = self.scene().views()[0]
            rect_ = view.mapFromScene(self.tooltip.sceneBoundingRect()).boundingRect()
            pos = self.boundingRect().topRight()
            mouse_pos = view.mapFromScene(event.scenePos())
            if mouse_pos.x() + rect_.width() >= view.viewport().width():
                pos = QPointF(-self.tooltip.boundingRect().width(), 0)

            self.tooltip.setPos(pos)

        self.color_animation.setDuration(200)
        self.color_animation.setStartValue(self.logic.idle_color())
        self.color_animation.setEndValue(self.logic.hover_enter_color())
        self.scene().update()
        if self.current_timer >= 0:
            self.killTimer(self.current_timer)
        self.color_animation.start()
        self.current_timer = self.startTimer(self.color_animation.duration() // 80)

    def hoverLeaveEvent(self, event: QGraphicsSceneHoverEvent):
        if self.disabled or self.mode == ButtonMode.Label:
            return

        self.hovered_.emit({'btn_id': self.btn_id, 'button': self, 'hovered': False})
        self.hovered = False
        self.tooltip_shown = False
        self.tooltip.setVisible(False)

        self.color_animation.setDuration(200)
        self.color_animation.setStartValue(self.logic.hover_enter_color())
        self.color_animation.setEndValue(self.logic.hover_left_color())
        self.scene().update()
        if self.current_timer > 0:
            self.killTimer(self.current_timer)
        self.color_animation.start()
        self.current_timer = self.startTimer(self.color_animation.duration() // 80)

    def hoverMoveEvent(self, event: QGraphicsSceneHoverEvent):
        pass

    @pyqtProperty(QColor)
    def current_fill_color(self):
        return self.fill_color_current

    @current_fill_color.setter
    def current_fill_color(self, color: QColor):
        self.fill_color_current = color

    def timerEvent(self, ev: QTimerEvent):
        self.scene().update()
        if self.color_animation.state() == QPropertyAnimation.Stopped:
            self.killTimer(ev.timerId())
            self.current_timer = 0

    def set_base_color(self, colors: List[ButtonColor]):
        self.logic.set_colors(colors)
        self.fill_color_current = self.logic.idle_color()

    def is_on(self):
        return self.logic.is_down()

    def set_on(self, value: bool):
        if isinstance(self.logic, CheckbuttonLogic):
            self.logic.down = value
            self.fill_color_current = self.logic.press_color() if value else self.logic.idle_color()
            self.update()

    def set_is_check_button(self, value: bool):
        if value:
            self.logic = CheckbuttonLogic()
        else:
            self.logic = PushbuttonLogic("gray")

    def set_pixmap(self, pixmap: QPixmap):
        if pixmap is not None:
            self.pixmap = pixmap.scaledToHeight(self.max_pixmap_height * self.scaling) if pixmap is not None else None
            self.fit_to_contents()

    def fit_to_contents(self):
        self.prepareGeometryChange()
        width = 2 * self.hor_margin * self.label.scale()
        height = 2 * self.ver_margin * self.label.scale() + self.label.boundingRect().height() * self.label.scale()
        if self.pixmap is not None:
            width += max(self.pixmap.width(), self.label.boundingRect().width() * self.label.scale())
            height += self.ver_margin * self.scaling + self.pixmap.height()
        else:
            width += self.label.boundingRect().width() * self.label.scale()
        self.rect.setWidth(width)
        self.rect.setHeight(height)

        self.label.setPos(0.5 * width - 0.5 * self.label.boundingRect().width() * self.label.scale() + 0.0 * self.hor_margin,
                          height - self.label.boundingRect().height() * self.label.scale() - self.ver_margin * self.scaling)
        self.update()

    def adjust_text_to_button(self):
        height_diff = 0.75 * self.rect.height() - self.label.boundingRect().height()
        fac = height_diff / (0.75 * self.rect.height())
        self.label.setTransformOriginPoint(self.label.boundingRect().center())
        self.label.setScale(1.0 + fac)
        self._reposition_text()

    def set_label(self, text: str, direction: str = 'horizontal'):
        if direction == 'vertical':
            text = '\n'.join(list(text))
        self.label.setText(text)
        self._reposition_text()

    def click_button(self, artificial_emit: bool = False):
        if self.disabled:
            return
        self.logic.do_click()
        self.fill_color_current = self.logic.release_color() if not artificial_emit else self.logic.idle_color()
        self.clicked.emit({"btn_id": self.btn_id, "btn_label": self.label, "button": self, 'checked': self.is_on()})
        if artificial_emit:
            self.hovered_.emit({'btn_id': self.btn_id, 'button': self, 'hovered': False})
            self.update()
        if self.scene() is not None:
            self.scene().update()

    def set_opacity(self, opacity: float):
        self.setOpacity(opacity)
        self.update()

    def set_default_state(self):
        self.logic.reset_state()
        self.fill_color_current = self.logic.idle_color()
        self.tooltip.setVisible(False)
        self.tooltip_shown = False
        self.update()

    def set_disabled(self, disabled: bool):
        self.disabled = disabled
        if disabled:
            self.label.setBrush(QBrush(self.text_color_disabled))
            self.fill_color_current = self.fill_color_disabled
        else:
            self.label.setBrush(QBrush(self.text_color_enabled))
            self.fill_color_current = self.logic.idle_color()
        self.update()

    def set_tooltip(self, tooltip: str):
        self.tooltip.setVisible(False)
        self.tooltip_shown = False
        self.tooltip.setText(tooltip)

    def set_custom_color(self, colors: List[QColor]):
        if isinstance(self.logic, CheckbuttonLogic):
            if len(colors) < 2:
                return
            self.logic.set_colors(colors=[
                colors[0],
                colors[0].lighter(120),
                colors[0].darker(120),

                colors[1],
                colors[1].lighter(120),
                colors[1].darker(120)
            ])
        else:
            self.logic.set_colors(colors=[
                colors[0],
                colors[0].lighter(120),
                colors[0].darker(120)
            ])
        self.fill_color_current = self.logic.idle_color()
        self.update()

    def set_mode(self, mode: ButtonMode):
        self.mode = mode
예제 #14
0
class UiTasklist(object):
    def setup(self, Dialog):
        Dialog.setObjectName("TaskList")
        Dialog.setEnabled(True)
        Dialog.setWindowFlags(QtCore.Qt.FramelessWindowHint)

        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed,
                                           QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(Dialog.sizePolicy().hasHeightForWidth())
        Dialog.setSizePolicy(sizePolicy)
        Dialog.setStyleSheet(CSS)
        self.label_3 = QtWidgets.QLabel(Dialog)
        self.label_3.setGeometry(QtCore.QRect(100, 0, 91, 16))
        self.label_3.setObjectName("label_3")
        self.verticalLayoutWidget = QtWidgets.QWidget(Dialog)
        self.verticalLayoutWidget.setGeometry(QtCore.QRect(0, 0, 341, 541))
        self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
        self.verticalLayout.setSizeConstraint(QtWidgets.QLayout.SetFixedSize)
        self.verticalLayout.setContentsMargins(0, 0, 0, 0)
        self.verticalLayout.setSpacing(0)
        self.verticalLayout.setObjectName("verticalLayout")
        self.verticalLayout_2 = QtWidgets.QVBoxLayout()
        self.verticalLayout_2.setSizeConstraint(
            QtWidgets.QLayout.SetMaximumSize)
        self.verticalLayout_2.setContentsMargins(0, 0, 0, 6)
        self.verticalLayout_2.setSpacing(4)
        self.verticalLayout_2.setObjectName("verticalLayout_2")
        self.lbl_status = QtWidgets.QLabel(self.verticalLayoutWidget)
        font = QtGui.QFont()
        font.setPointSize(10)
        font.setBold(True)
        font.setWeight(75)
        self.lbl_status.setFont(font)
        self.lbl_status.setAlignment(QtCore.Qt.AlignCenter)
        self.lbl_status.setObjectName("lbl_status")
        self.verticalLayout_2.addWidget(self.lbl_status)
        self.label_2 = QtWidgets.QLabel(self.verticalLayoutWidget)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                           QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.label_2.sizePolicy().hasHeightForWidth())
        self.label_2.setSizePolicy(sizePolicy)
        font = QtGui.QFont()
        font.setPointSize(9)
        font.setBold(False)
        font.setWeight(50)
        self.label_2.setFont(font)
        self.label_2.setTextFormat(QtCore.Qt.AutoText)
        self.label_2.setScaledContents(False)
        self.label_2.setAlignment(QtCore.Qt.AlignCenter)
        self.label_2.setWordWrap(False)
        self.label_2.setObjectName("label_2")
        self.verticalLayout_2.addWidget(self.label_2)
        self.verticalLayout.addLayout(self.verticalLayout_2)
        self.listWidget = QtWidgets.QListWidget(self.verticalLayoutWidget)
        self.listWidget.setFixedHeight(460)
        self.listWidget.setFixedWidth(340)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                           QtWidgets.QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.listWidget.sizePolicy().hasHeightForWidth())
        self.listWidget.setSizePolicy(sizePolicy)
        self.listWidget.setAutoFillBackground(False)
        self.listWidget.setFrameShape(QtWidgets.QFrame.NoFrame)
        self.listWidget.setFrameShadow(QtWidgets.QFrame.Raised)
        self.listWidget.setHorizontalScrollBarPolicy(
            QtCore.Qt.ScrollBarAlwaysOff)
        self.listWidget.setEditTriggers(
            QtWidgets.QAbstractItemView.NoEditTriggers)
        self.listWidget.setSelectionMode(
            QtWidgets.QAbstractItemView.NoSelection)
        self.listWidget.setMovement(QtWidgets.QListView.Static)
        #self.listWidget.setProperty("isWrapping", False)
        self.listWidget.setResizeMode(QtWidgets.QListView.Fixed)
        self.listWidget.setLayoutMode(QtWidgets.QListView.SinglePass)
        self.listWidget.setViewMode(QtWidgets.QListView.ListMode)
        self.listWidget.setSelectionRectVisible(False)
        self.listWidget.setObjectName("listWidget")
        self.verticalLayout.addWidget(self.listWidget)
        self.retranslate(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslate(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "GSyncftp - Tasklist"))
        self.lbl_status.setText(
            _translate("TaskList", "O GSyncftp está atualizado"))
        self.label_2.setText(_translate("TaskList", " Enterprise Coorp. LTDA"))
        self.listWidget.setSortingEnabled(False)
        self.listWidget.addItem("Nenhum arquivo na fila")

    def status_sync(self):
        _translate = QtCore.QCoreApplication.translate
        self.lbl_status.setText(
            _translate("TaskList", "Enviando os arquivos..."))

    def status_synced(self):
        _translate = QtCore.QCoreApplication.translate
        self.lbl_status.setText(
            _translate("TaskList", "O GSyncftp está atualizado"))

    def do_animation(self, Dialog):
        size_screen = QtWidgets.QDesktopWidget().screenGeometry(-1)
        pt_x = size_screen.width() - 339
        pt_y = size_screen.height() - 537
        self.anim = QPropertyAnimation(Dialog, b"geometry")
        self.anim.setDuration(250)
        self.anim.setStartValue(QRect(pt_x, size_screen.height(), 339, 537))
        self.anim.setEndValue(QRect(pt_x, pt_y, 339, 537))
        self.anim.start()
        Dialog.setEnabled(True)

    def not_in_animation(self):
        return self.anim and self.anim.state() != 2
예제 #15
0
class CircleFillAnimator(AbstractAnimator):
    m_decorator: CircleFillDecorator
    m_animation: QPropertyAnimation
    m_hideAfterFinish = True

    def __init__(self, _widgetForFill):
        super(CircleFillAnimator, self).__init__(_widgetForFill)

        self.m_decorator = CircleFillDecorator(_widgetForFill)
        self.m_animation = QPropertyAnimation(self.m_decorator, b"_radius")

        _widgetForFill.installEventFilter(self)

        self.m_animation.setDuration(500)

        self.m_decorator.setAttribute(Qt.WA_TransparentForMouseEvents)
        self.m_decorator.hide()

        def finished():
            self.setAnimatedStopped()
            if self.m_hideAfterFinish:
                self.hideDecorator()

        self.m_animation.finished.connect(finished)

    def setStartPoint(self, _point):
        self.m_decorator.setStartPoint(_point)

    def setFillColor(self, _color):
        self.m_decorator.setFillColor(_color)

    def setHideAfterFinish(self, _hide):
        self.m_hideAfterFinish = _hide

    def animationDuration(self):
        return self.m_animation.duration()

    def animateForward(self):
        self.fillIn()

    def fillIn(self):
        if self.isAnimated() and self.isAnimatedForward():
            return
        self.setAnimatedForward()

        startRadius = 0
        finalRadius = math.sqrt(
            self.widgetForFill().height() * self.widgetForFill().height() +
            self.widgetForFill().width() * self.widgetForFill().width())

        self.m_decorator.resize(self.widgetForFill().size())
        self.m_decorator.move(0, 0)
        self.m_decorator.show()
        self.m_decorator.raise_()

        if self.m_animation.state() == QPropertyAnimation.Running:
            self.m_animation.pause()
            self.m_animation.setDirection(QPropertyAnimation.Backward)
            self.m_animation.resume()
        else:
            self.m_animation.setEasingCurve(QEasingCurve.OutQuart)
            self.m_animation.setDirection(QPropertyAnimation.Forward)
            self.m_animation.setStartValue(startRadius)
            self.m_animation.setEndValue(finalRadius)
            self.m_animation.start()

    def animateBackward(self):
        self.fillOut()

    def fillOut(self):
        if self.isAnimated() and self.isAnimatedBackward():
            return
        self.setAnimatedBackward()

        startRadius = math.sqrt(
            self.widgetForFill().height() * self.widgetForFill().height() +
            self.widgetForFill().width() * self.widgetForFill().width())
        finalRadius = 0

        self.m_decorator.resize(self.widgetForFill().size())
        self.m_decorator.move(0, 0)
        self.m_decorator.show()
        self.m_decorator.raise_()

        if self.m_animation.state() == QPropertyAnimation.Running:
            self.m_animation.pause()
            self.m_animation.setDirection(QPropertyAnimation.Backward)
            self.m_animation.resume()
        else:
            self.m_animation.setEasingCurve(QEasingCurve.OutQuart)
            self.m_animation.setDirection(QPropertyAnimation.Forward)
            self.m_animation.setStartValue(startRadius)
            self.m_animation.setEndValue(finalRadius)
            self.m_animation.start()

    def hideDecorator(self):
        hideEffect = self.m_decorator.graphicsEffect()
        if hideEffect == None:
            hideEffect = QGraphicsOpacityEffect(self.m_decorator)
            self.m_decorator.setGraphicsEffect(hideEffect)
        hideEffect.setOpacity(1)

        hideAnimation = QPropertyAnimation(hideEffect, b"opacity",
                                           self.m_decorator)
        hideAnimation.setDuration(400)
        hideAnimation.setStartValue(1)
        hideAnimation.setEndValue(0)

        def finished():
            self.m_decorator.hide()
            hideEffect.setOpacity(1)

        hideAnimation.finished.connect(finished)

        hideAnimation.start(QAbstractAnimation.DeleteWhenStopped)

    def widgetForFill(self):
        return self.parent()
예제 #16
0
파일: ui.py 프로젝트: xmye/games
    class QTile(QGraphicsObject):
        colorMap = {
            Tetris.I: QColor("#53bbf4"),
            Tetris.J: QColor("#e25fb8"),
            Tetris.L: QColor("#ffac00"),
            Tetris.O: QColor("#ecff2e"),
            Tetris.S: QColor("#97eb00"),
            Tetris.T: QColor("#ff85cb"),
            Tetris.Z: QColor("#ff5a48")
        }

        def __init__(self, qTetris: 'QTetris', tetrimino: Tetris.Tetrimino,
                     tile: Tetris.Tile):
            super(QTetris.QTile, self).__init__()
            tile.delegate = self
            self.color = self.colorMap[type(tetrimino)]
            self.qTetris = qTetris
            self.moveAnimation = QParallelAnimationGroup()
            self.dropAnimation = QPropertyAnimation(self, b'pos')
            self.collapseAnimation = QPropertyAnimation(self, b'pos')
            self.shiftAnimation = QPropertyAnimation(self, b'pos')
            self.collapseAnimation.finished.connect(
                lambda tl=tile: tile.delegate.disappeared(tl))
            self.qTetris.scene.addItem(self)
            self.setPos(QPointF(0, 4))
            self.moved(tile)

        def moved(self, tile: Tetris.Tile):
            translation = QPropertyAnimation(self, b'pos')
            start, end = self.pos(), QPointF(tile.row, tile.column)
            curve, speed, delay = QEasingCurve.OutBack, 1 / 50, -1
            self.animate(translation, start, end, curve, speed, delay)

            rotation = QPropertyAnimation(self, b'rotation')
            start, end = self.rotation(), tile.rotation
            curve, speed, delay = QEasingCurve.OutBack, 1, -1
            self.animate(rotation, start, end, curve, speed, delay)
            rotation.setDuration(translation.duration())

            self.moveAnimation.clear()
            self.moveAnimation.addAnimation(translation)
            self.moveAnimation.addAnimation(rotation)
            self.moveAnimation.start()

        def dropped(self, tile: Tetris.Tile):
            start, end = self.pos(), QPointF(tile.row, tile.column)
            curve, speed, delay = QEasingCurve.OutBounce, 1 / 50, 0
            self.animate(self.dropAnimation, start, end, curve, speed, delay)

        def collapsed(self, tile: Tetris.Tile):
            start, end = self.pos(), QPointF(
                tile.row, tile.column + 2 * tile.tetris.num_columns)
            curve, speed, delay = QEasingCurve.InOutExpo, 1 / 50, 800
            if self.dropAnimation.state() == QAbstractAnimation.Running:
                start = self.dropAnimation.endValue()
            self.animate(self.collapseAnimation, start, end, curve, speed,
                         delay)

        def shifted(self, tile: Tetris.Tile):
            start, end = self.pos(), QPointF(tile.row, tile.column)
            curve, speed, delay = QEasingCurve.OutBounce, 1 / 100, 1200
            if self.dropAnimation.state() == QAbstractAnimation.Running:
                start = self.dropAnimation.endValue()
            self.animate(self.shiftAnimation, start, end, curve, speed, delay)

        def disappeared(self, tile: Tetris.Tile):
            self.qTetris.scene.removeItem(self)

        def paint(self,
                  painter: QPainter,
                  styleOption: QStyleOptionGraphicsItem,
                  widget: QWidget = None):
            pen = QPen()
            pen.setWidthF(0.05)
            pen.setColor(Qt.darkGray)
            painter.setPen(pen)
            brush = QBrush()
            brush.setColor(self.color)
            brush.setStyle(Qt.SolidPattern)
            painter.setBrush(brush)
            topLeft = QPointF(0, 0)
            bottomRight = QPointF(1, 1)
            rectangle = QRectF(topLeft, bottomRight)
            rectangle.translate(-0.5, -0.5)
            painter.drawRect(rectangle)

        @staticmethod
        def animate(animation: QPropertyAnimation,
                    start: Union[QPointF, int, float],
                    end: Union[QPointF, int, float],
                    curve: QEasingCurve = QEasingCurve.Linear,
                    speed: float = 1 / 50,
                    delay: int = -1):
            animation.setStartValue(start)
            animation.setEndValue(end)
            animation.setEasingCurve(curve)
            if type(start) == type(end) == QPointF:
                distance = (end - start).manhattanLength()
            else:
                distance = abs(end - start)
            animation.setDuration(round(distance / speed))
            if delay == 0:
                animation.start()
            if delay > 0:
                QTimer.singleShot(delay, animation.start)

        def boundingRect(self):
            topLeft = QPointF(0, 0)
            bottomRight = QPointF(1, 1)
            rectangle = QRectF(topLeft, bottomRight)
            rectangle.translate(-0.5, -0.5)
            return rectangle
예제 #17
0
class StackedWidgetFadeInAnimator(AbstractAnimator):
    m_decorator: StackedWidgetFadeInDecorator
    m_animation: QPropertyAnimation

    def __init__(self, _container, _fadeWidget):
        super(StackedWidgetFadeInAnimator, self).__init__(_container)

        self.m_decorator = StackedWidgetFadeInDecorator(_container, _fadeWidget=_fadeWidget)
        self.m_animation = QPropertyAnimation(self.m_decorator, b"opacity")

        _container.installEventFilter(self)

        self.m_animation.setDuration(200)

        self.m_decorator.hide()

        def finished():
            self.setAnimatedStopped()

            if self.m_animation.direction() == QPropertyAnimation.Forward:
                _container.setCurrentWidget(_fadeWidget)
            self.m_decorator.hide()

        self.m_animation.finished.connect(finished)

    def animationDuration(self):
        return self.m_animation.duration()

    def animateForward(self):
        self.fadeIn()

    def fadeIn(self):
        if self.isAnimated() and self.isAnimatedForward():
            return
        self.setAnimatedForward()

        self.m_decorator.grabContainer()
        self.m_decorator.grabFadeWidget()

        startOpacity = 0
        finalOpacity = 1

        self.m_decorator.setOpacity(startOpacity)
        self.m_decorator.move(0, 0)
        self.m_decorator.show()
        self.m_decorator.raise_()

        if self.m_animation.state() == QPropertyAnimation.Running:
            self.m_animation.pause()
            self.m_animation.setDirection(QPropertyAnimation.Backward)
            self.m_animation.resume()
        else:
            self.m_animation.setEasingCurve(QEasingCurve.InQuad)
            self.m_animation.setDirection(QPropertyAnimation.Forward)
            self.m_animation.setStartValue(startOpacity)
            self.m_animation.setEndValue(finalOpacity)

            self.m_animation.start()

    def eventFilter(self, _object, _event):
        if _object == self.fadeWidget() and _event.type() == QEvent.Resize and self.m_decorator.isVisible():
            self.m_decorator.grabContainer()
            self.m_decorator.grabFadeWidget()

        return QWidget.eventFilter(self, _object, _event)

    def fadeWidget(self):
        return self.parent()
예제 #18
0
    class QTetritile(QGraphicsObject):
        colorMap = {
            Tetris.I: QColor("#53bbf4"),
            Tetris.J: QColor("#e25fb8"),
            Tetris.L: QColor("#ffac00"),
            Tetris.O: QColor("#ecff2e"),
            Tetris.S: QColor("#97eb00"),
            Tetris.T: QColor("#ff85cb"),
            Tetris.Z: QColor("#ff5a48")
        }

        def __init__(self, tetris, tetritile):
            super(QTetris.QTetritile, self).__init__()
            tetritile.delegate = self
            self.color = self.colorMap[type(tetritile.tetrimino)]
            self.tetris = tetris
            self.moveAnimation = QSequentialAnimationGroup()
            self.dropAnimation = QPropertyAnimation(self, b"pos")
            self.collapseAnimation = QPropertyAnimation(self, b"pos")
            self.shiftAnimation = QPropertyAnimation(self, b"pos")
            self.collapseAnimation.finished.connect(
                lambda tetritile=tetritile: self.tetris.disappearEvent(
                    tetritile))
            self.tetris.scene.addItem(self)
            self.setPos(QPointF(0, 4))
            self.moveEvent(tetritile)

        def moveEvent(self, tetritile):
            translation = QPropertyAnimation(self, b"pos")
            start, end = self.pos(), QPointF(tetritile.row, tetritile.column)
            curve, speed, delay = QEasingCurve.OutBack, 1 / 50, -1
            self.animate(translation, start, end, curve, speed, delay)

            rotation = QPropertyAnimation(self, b"rotation")
            start, end = self.rotation(), tetritile.rotation
            curve, speed, delay = QEasingCurve.OutBack, 1, -1
            self.animate(rotation, start, end, curve, speed, delay)
            rotation.setDuration(translation.duration())

            self.moveAnimation.clear()
            self.moveAnimation.addAnimation(translation)
            self.moveAnimation.addAnimation(rotation)
            self.moveAnimation.start()

        def dropEvent(self, tetritile):
            start, end = self.pos(), QPointF(tetritile.row, tetritile.column)
            curve, speed, delay = QEasingCurve.OutBounce, 1 / 50, 0
            self.animate(self.dropAnimation, start, end, curve, speed, delay)

        def collapseEvent(self, tetritile):
            start, end = self.pos(), QPointF(
                tetritile.row,
                tetritile.column + self.tetris.tetris.columns + 5)
            curve, speed, delay = QEasingCurve.InOutExpo, 1 / 50, 800
            if self.dropAnimation.state() == QAbstractAnimation.Running:
                start = self.dropAnimation.endValue()
            self.animate(self.collapseAnimation, start, end, curve, speed,
                         delay)

        def shiftEvent(self, tetritile):
            start, end = self.pos(), QPointF(tetritile.row, tetritile.column)
            curve, speed, delay = QEasingCurve.OutBounce, 1 / 100, 1200
            if self.dropAnimation.state() == QAbstractAnimation.Running:
                start = self.dropAnimation.endValue()
            self.animate(self.shiftAnimation, start, end, curve, speed, delay)

        def paint(self, painter, styleOption, widget=None):
            pen = QPen()
            pen.setWidthF(0.05)
            pen.setColor(Qt.darkGray)
            painter.setPen(pen)
            brush = QBrush()
            brush.setColor(self.color)
            brush.setStyle(Qt.SolidPattern)
            painter.setBrush(brush)
            topLeft = QPointF(0, 0)
            bottomRight = QPointF(1, 1)
            rectangle = QRectF(topLeft, bottomRight)
            rectangle.translate(-0.5, -0.5)
            painter.drawRect(rectangle)

        def animate(self,
                    animation,
                    start,
                    end,
                    curve=QEasingCurve.Linear,
                    speed=1 / 50,
                    delay=-1):
            animation.setStartValue(start)
            animation.setEndValue(end)
            animation.setEasingCurve(curve)
            try:
                animation.setDuration((end - start).manhattanLength() / speed)
            except AttributeError:
                animation.setDuration(abs(end - start) / speed)
            if delay == 0:
                animation.start()
            if delay > 0:
                QTimer.singleShot(delay, animation.start)

        def boundingRect(self):
            topLeft = QPointF(0, 0)
            bottomRight = QPointF(1, 1)
            rectangle = QRectF(topLeft, bottomRight)
            rectangle.translate(-0.5, -0.5)
            return rectangle
예제 #19
0
class CAvatar(QWidget):

    Circle = 0  # 圆圈
    Rectangle = 1  # 圆角矩形
    SizeLarge = QSize(128, 128)
    SizeMedium = QSize(64, 64)
    SizeSmall = QSize(32, 32)
    StartAngle = 0  # 起始旋转角度
    EndAngle = 360  # 结束旋转角度

    def __init__(self,
                 *args,
                 shape=0,
                 url='',
                 cacheDir=False,
                 size=QSize(64, 64),
                 animation=False,
                 **kwargs):
        super(CAvatar, self).__init__(*args, **kwargs)
        self.url = ''
        self._angle = 0  # 角度
        self.pradius = 0  # 加载进度条半径
        self.animation = animation  # 是否使用动画
        self._movie = None  # 动态图
        self._pixmap = QPixmap()  # 图片对象
        self.pixmap = QPixmap()  # 被绘制的对象
        self.isGif = url.endswith('.gif')
        # 进度动画定时器
        self.loadingTimer = QTimer(self, timeout=self.onLoading)
        # 旋转动画
        self.rotateAnimation = QPropertyAnimation(self,
                                                  b'angle',
                                                  self,
                                                  loopCount=1)
        self.setShape(shape)
        self.setCacheDir(cacheDir)
        self.setSize(size)
        self.setUrl(url)

    def paintEvent(self, event):
        super(CAvatar, self).paintEvent(event)
        # 画笔
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing, True)
        painter.setRenderHint(QPainter.HighQualityAntialiasing, True)
        painter.setRenderHint(QPainter.SmoothPixmapTransform, True)
        # 绘制
        path = QPainterPath()
        diameter = min(self.width(), self.height())
        if self.shape == self.Circle:
            radius = int(diameter / 2)
        elif self.shape == self.Rectangle:
            radius = 4
        halfW = self.width() / 2
        halfH = self.height() / 2
        painter.translate(halfW, halfH)
        path.addRoundedRect(QRectF(-halfW, -halfH, diameter, diameter), radius,
                            radius)
        painter.setClipPath(path)
        # 如果是动画效果
        if self.rotateAnimation.state() == QPropertyAnimation.Running:
            painter.rotate(self._angle)  # 旋转
            painter.drawPixmap(
                QPointF(-self.pixmap.width() / 2, -self.pixmap.height() / 2),
                self.pixmap)
        else:
            painter.drawPixmap(-int(halfW), -int(halfH), self.pixmap)
        # 如果在加载
        if self.loadingTimer.isActive():
            diameter = 2 * self.pradius
            painter.setBrush(
                QColor(45, 140, 240, (1 - self.pradius / 10) * 255))
            painter.setPen(Qt.NoPen)
            painter.drawRoundedRect(
                QRectF(-self.pradius, -self.pradius, diameter, diameter),
                self.pradius, self.pradius)

    def enterEvent(self, event):
        """鼠标进入动画
        :param event:
        """
        if not (self.animation and not self.isGif):
            return
        self.rotateAnimation.stop()
        cv = self.rotateAnimation.currentValue() or self.StartAngle
        self.rotateAnimation.setDuration(540 if cv ==
                                         0 else int(cv / self.EndAngle * 540))
        self.rotateAnimation.setStartValue(cv)
        self.rotateAnimation.setEndValue(self.EndAngle)
        self.rotateAnimation.start()

    def leaveEvent(self, event):
        """鼠标离开动画
        :param event:
        """
        if not (self.animation and not self.isGif):
            return
        self.rotateAnimation.stop()
        cv = self.rotateAnimation.currentValue() or self.EndAngle
        self.rotateAnimation.setDuration(int(cv / self.EndAngle * 540))
        self.rotateAnimation.setStartValue(cv)
        self.rotateAnimation.setEndValue(self.StartAngle)
        self.rotateAnimation.start()

    def onLoading(self):
        """更新进度动画
        """
        if self.loadingTimer.isActive():
            if self.pradius > 9:
                self.pradius = 0
            self.pradius += 1
        else:
            self.pradius = 0
        self.update()

    def onFinished(self):
        """图片下载完成
        """
        self.loadingTimer.stop()
        self.pradius = 0
        reply = self.sender()

        if self.isGif:
            self._movie = QMovie(reply, b'gif', self)
            if self._movie.isValid():
                self._movie.frameChanged.connect(self._resizeGifPixmap)
                self._movie.start()
        else:
            data = reply.readAll().data()
            reply.deleteLater()
            del reply
            self._pixmap.loadFromData(data)
            if self._pixmap.isNull():
                self._pixmap = QPixmap(self.size())
                self._pixmap.fill(QColor(204, 204, 204))
            self._resizePixmap()

    def onError(self, code):
        """下载出错了
        :param code:
        """
        self._pixmap = QPixmap(self.size())
        self._pixmap.fill(QColor(204, 204, 204))
        self._resizePixmap()

    def refresh(self):
        """强制刷新
        """
        self._get(self.url)

    def isLoading(self):
        """判断是否正在加载
        """
        return self.loadingTimer.isActive()

    def setShape(self, shape):
        """设置形状
        :param shape:        0=圆形, 1=圆角矩形
        """
        self.shape = shape

    def setUrl(self, url):
        """设置url,可以是本地路径,也可以是网络地址
        :param url:
        """
        self.url = url
        self._get(url)

    def setCacheDir(self, cacheDir=''):
        """设置本地缓存路径
        :param cacheDir:
        """
        self.cacheDir = cacheDir
        self._initNetWork()

    def setSize(self, size):
        """设置固定尺寸
        :param size:
        """
        if not isinstance(size, QSize):
            size = self.SizeMedium
        self.setMinimumSize(size)
        self.setMaximumSize(size)
        self._resizePixmap()

    @pyqtProperty(int)
    def angle(self):
        return self._angle

    @angle.setter
    def angle(self, value):
        self._angle = value
        self.update()

    def _resizePixmap(self):
        """缩放图片
        """
        if not self._pixmap.isNull():
            self.pixmap = self._pixmap.scaled(self.width(), self.height(),
                                              Qt.IgnoreAspectRatio,
                                              Qt.SmoothTransformation)
        self.update()

    def _resizeGifPixmap(self, _):
        """缩放动画图片
        """
        if self._movie:
            self.pixmap = self._movie.currentPixmap().scaled(
                self.width(), self.height(), Qt.IgnoreAspectRatio,
                Qt.SmoothTransformation)
        self.update()

    def _initNetWork(self):
        """初始化异步网络库
        """
        if not hasattr(qApp, '_network'):
            network = QNetworkAccessManager(self.window())
            setattr(qApp, '_network', network)
        # 是否需要设置缓存
        if self.cacheDir and not qApp._network.cache():
            cache = QNetworkDiskCache(self.window())
            cache.setCacheDirectory(self.cacheDir)
            qApp._network.setCache(cache)

    def _get(self, url):
        """设置图片或者请求网络图片
        :param url:
        """
        if not url:
            self.onError('')
            return
        if url.startswith('http') and not self.loadingTimer.isActive():
            url = QUrl(url)
            request = QNetworkRequest(url)
            request.setHeader(QNetworkRequest.UserAgentHeader, b'CAvatar')
            request.setRawHeader(b'Author', b'Irony')
            request.setAttribute(QNetworkRequest.FollowRedirectsAttribute,
                                 True)
            if qApp._network.cache():
                request.setAttribute(QNetworkRequest.CacheLoadControlAttribute,
                                     QNetworkRequest.PreferNetwork)
                request.setAttribute(QNetworkRequest.CacheSaveControlAttribute,
                                     True)
            reply = qApp._network.get(request)
            self.pradius = 0
            self.loadingTimer.start(50)  # 显示进度动画
            reply.finished.connect(self.onFinished)
            reply.error.connect(self.onError)
            return
        self.pradius = 0
        if os.path.exists(url) and os.path.isfile(url):
            if self.isGif:
                self._movie = QMovie(url, parent=self)
                if self._movie.isValid():
                    self._movie.frameChanged.connect(self._resizeGifPixmap)
                    self._movie.start()
            else:
                self._pixmap = QPixmap(url)
                self._resizePixmap()
        else:
            self.onError('')
class ExpandAnimator(AbstractAnimator):
    m_decorator: ExpandDecorator
    m_animation: QPropertyAnimation
    m_expandRect: QRect

    def __init__(self, _widgetForFill):
        super(ExpandAnimator, self).__init__(_widgetForFill)

        self.m_decorator = ExpandDecorator(_widgetForFill)
        self.m_animation = QPropertyAnimation(self.m_decorator, b"_expandRect")

        _widgetForFill.installEventFilter(self)

        self.m_animation.setDuration(400)

        self.m_decorator.hide()

        def finished():
            self.setAnimatedStopped()
            if self.isAnimatedBackward():
                self.m_decorator.hide()

        self.m_animation.finished.connect(finished)

    def setExpandRect(self, _rect):
        self.m_expandRect = _rect
        self.m_decorator.setExpandRect(_rect)

    def setFillColor(self, _color):
        self.m_decorator.setFillColor(_color)

    def animationDuration(self):
        return self.m_animation.duration()

    def animateForward(self):
        self.expandIn()

    def expandIn(self):
        if self.isAnimated() and self.isAnimatedForward():
            return
        self.setAnimatedForward()

        startExpandRect = self.m_expandRect
        finalExpandRect = self.widgetForFill().rect()

        self.m_decorator.resize(self.widgetForFill().size())
        self.m_decorator.move(0, 0)
        self.m_decorator.grabExpandRect()
        self.m_decorator.show()
        self.m_decorator.raise_()

        if self.m_animation.state() == QPropertyAnimation.Running:
            self.m_animation.pause()
            self.m_animation.setDirection(QPropertyAnimation.Backward)
            self.m_animation.resume()
        else:
            self.m_animation.setEasingCurve(QEasingCurve.InOutQuart)
            self.m_animation.setDirection(QPropertyAnimation.Forward)
            self.m_animation.setStartValue(startExpandRect)
            self.m_animation.setEndValue(finalExpandRect)
            self.m_animation.start()

    def animateBackward(self):
        self.expandOut()

    def expandOut(self):
        if self.isAnimated() and self.isAnimatedBackward():
            return
        self.setAnimatedBackward()

        startExpandRect = self.widgetForFill().rect()
        finalExpandRect = self.m_expandRect

        self.m_decorator.resize(self.widgetForFill().size())
        self.m_decorator.move(0, 0)
        self.m_decorator.hide()
        self.m_decorator.grabExpandRect()
        self.m_decorator.show()
        self.m_decorator.raise_()

        if self.m_animation.state() == QPropertyAnimation.Running:
            self.m_animation.pause()
            self.m_animation.setDirection(QPropertyAnimation.Backward)
            self.m_animation.resume()
        else:
            self.m_animation.setEasingCurve(QEasingCurve.InOutQuart)
            self.m_animation.setDirection(QPropertyAnimation.Forward)
            self.m_animation.setStartValue(startExpandRect)
            self.m_animation.setEndValue(finalExpandRect)
            self.m_animation.start()

    def eventFilter(self, _object, _event):
        if _object == self.widgetForFill() and _event.type(
        ) == QEvent.Resize and self.m_decorator.isVisible():
            self.m_decorator.resize(self.widgetForFill().size())
            self.m_animation.setEndValue(self.widgetForFill().rect())

        return QObject.eventFilter(self, _object, _event)

    def widgetForFill(self):
        return self.parent()
예제 #21
0
class PopupWidget(QtWidgets.QWidget):

    #   enum PointerPosition
    LeftSide = 0
    RightSide = 1
    TopSide = 2
    BottomSide = 3
    NoPointer = 4

    LR_MARGIN = 10.0  #8.0 #/* left / right margin  */
    TB_MARGIN = 8.0  #5.5 #/* top / bottom margin */

    didHide = pyqtSignal()
    didShow = pyqtSignal()
    onClick = pyqtSignal()
    onRightClick = pyqtSignal()

    def __init__(self,
                 parent=None,
                 timeout=None,
                 delete_on_hide=True,
                 activation_hides=True,
                 dark_mode=False):
        ''' parent should be a window or None
            timeout is the amount of time, in milliseconds, to show the widget before it is auto-hidden. None is no timeout.
            delete_on_hide, if True, will auto-delete this widget after it is hidden due to the timeout or due to calling hide().
        '''
        super().__init__(parent)
        self.layout = QtWidgets.QGridLayout(self)
        if sys.platform != 'darwin':
            self.layout.setContentsMargins(20, 20, 20, 20)
        self.animation = QPropertyAnimation(self)
        self.final_opacity = 1.0
        self.popup_opacity = 1.0
        self.pointerPos = self.LeftSide
        self._timer = None
        self.activation_hides = activation_hides
        self.dark_mode = dark_mode and sys.platform.lower() != "darwin"

        #self.resize(200, 50)

        self.setWindowFlags(Qt.FramelessWindowHint | Qt.Tool)
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.setAttribute(Qt.WA_ShowWithoutActivating)

        self.animation.setTargetObject(self)
        self.animation.setPropertyName(b'popupOpacity')
        self.animation.setDuration(200)

        self.setLayout(self.layout)

        if parent: parent.installEventFilter(self)

        self.timeout = timeout
        self.delete_on_hide = delete_on_hide

    def getPointerPosition(self):
        return self.pointerPos

    def setPointerPosition(self, r):
        self.pointerPos = r
        self.update()

    @pyqtProperty(
        float
    )  # Property so that Qt animations work. You may set the actual attrbute directly and ingore this in client code
    def popupOpacity(self):
        return self.popup_opacity

    @popupOpacity.setter
    def popupOpacity(self, value):
        self.popup_opacity = value
        self.setWindowOpacity(value)

    @pyqtProperty(
        float
    )  # Property so that Qt animations work. You may set the actual attrbute directly and ingore this in client code
    def finalOpacity(self):
        return self.final_opacity

    @finalOpacity.setter
    def finalOpacity(self, value):
        self.final_opacity = value

    def paintEvent(self, e):
        #// Draw the popup here
        #// You can always pick an image and use drawPixmap to
        #// draw it in order to make things simpler

        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)
        painter.setClipRegion(e.region())
        painter.fillRect(e.rect(), QColor(0, 0, 0, 0))

        #// Prepare the popup dimensions
        roundedRectDimensions = QRectF()
        roundedRectDimensions.setX(self.rect().x() + self.LR_MARGIN)
        roundedRectDimensions.setY(self.rect().y() + self.TB_MARGIN)
        roundedRectDimensions.setWidth(self.rect().width() -
                                       self.LR_MARGIN * 2.0)
        roundedRectDimensions.setHeight(self.rect().height() -
                                        self.TB_MARGIN * 2.0)

        pal = QPalette(self.palette())

        painter.setBrush(
            QBrush(
                pal.color(
                    QPalette.Window if self.dark_mode else QPalette.Mid)))

        pen = QPen()
        pen.setColor(
            pal.color(QPalette.Light if self.dark_mode else QPalette.Button))
        pen.setWidth(3)
        painter.setPen(pen)

        #// Draw the popup body
        painter.drawRoundedRect(roundedRectDimensions, self.LR_MARGIN * 2.0,
                                self.TB_MARGIN * 2.0)

        painter.setPen(Qt.NoPen)
        painter.setBrush(
            QBrush(
                pal.color(
                    QPalette.BrightText if self.dark_mode else QPalette.Dark)))
        #// Draw the popup pointer based on relPos
        self.drawPopupPointer(painter)

        e.accept()

    def drawPopupPointer(self, p):
        r = QRectF(self.rect())

        if self.pointerPos == self.LeftSide:
            PPIX_X = self.LR_MARGIN
            PPIX_Y = PPIX_X * 2.0
            points = [
                QPointF(r.x() + PPIX_X,
                        r.height() / 2.0 - PPIX_Y / 2.0),
                QPointF(r.x() + PPIX_X,
                        r.height() / 2.0 + PPIX_Y / 2.0),
                QPointF(r.x(),
                        r.height() / 2.0),
            ]

            p.drawPolygon(*points)

        if self.pointerPos == self.RightSide:
            PPIX_X = self.LR_MARGIN
            PPIX_Y = PPIX_X * 2.0
            points = [
                QPointF(r.right() - PPIX_X,
                        r.height() / 2.0 - PPIX_Y / 2.0),
                QPointF(r.right() - PPIX_X,
                        r.height() / 2.0 + PPIX_Y / 2.0),
                QPointF(r.right(),
                        r.height() / 2.0),
            ]

            p.drawPolygon(*points)

        if self.pointerPos == self.TopSide:
            PPIX_Y = self.TB_MARGIN
            PPIX_X = PPIX_Y * 2.0
            points = [
                QPointF(r.x() + r.width() / 2.0 - PPIX_X / 2.0,
                        r.top() + PPIX_Y),
                QPointF(r.x() + r.width() / 2.0 + PPIX_X / 2.0,
                        r.top() + PPIX_Y),
                QPointF(r.x() + r.width() / 2.0, r.top()),
            ]

            p.drawPolygon(*points)

        if self.pointerPos == self.BottomSide:
            PPIX_Y = self.TB_MARGIN
            PPIX_X = PPIX_Y * 2.0
            points = [
                QPointF(r.x() + r.width() / 2.0 - PPIX_X / 2.0,
                        r.bottom() - PPIX_Y),
                QPointF(r.x() + r.width() / 2.0 + PPIX_X / 2.0,
                        r.bottom() - PPIX_Y),
                QPointF(r.x() + r.width() / 2.0, r.bottom()),
            ]

            p.drawPolygon(*points)

    def showRelativeTo(self, w):
        s = self.size()
        self.moveRelativeTo(w)
        self.hide()
        self.show()
        if self.pointerPos == self.NoPointer:
            self.raise_()
        if s != self.size():
            # show caused widget resize.. recenter
            self.moveRelativeTo(w)

    def moveRelativeTo(self, w):
        if not w:
            print(
                "INTERNAL ERROR: PopupWidget::showRelativeTo got passed a NULL widget pointer! Ignoring.. FIXME!"
            )
            return

        p = w.mapToGlobal(QPoint(0, 0))
        if self.pointerPos == self.LeftSide:
            p.setX(p.x() + w.width())
            p.setY(p.y() - self.height() // 2 + w.height() // 2)
        elif self.pointerPos == self.RightSide:
            p.setX(p.x() - self.width())
            p.setY(p.y() - self.height() // 2 + w.height() // 2)
        elif self.pointerPos == self.BottomSide:
            p.setX(p.x() + w.width() // 2 - self.width() // 2)
            p.setY(p.y() - self.height())
        elif self.pointerPos == self.TopSide:
            p.setX(p.x() + w.width() // 2 - self.width() // 2)
            p.setY(p.y() + w.height())
        else:
            #// just center it on the widget
            p.setX(p.x() + w.width() // 2 - self.width() // 2)
            p.setY(p.y() + w.height() // 2 - self.height() // 2)
            if self.isVisible():
                self.raise_()

        self.move(p)

    def _killTimer(self):
        if self._timer:
            self._timer.stop()
            self._timer.deleteLater()
            self._timer = None

    def _startTimer(self, target):
        self._killTimer()
        self._timer = QTimer(self)
        self._timer.setSingleShot(True)

        def timeout():
            self._killTimer()
            target()

        self._timer.timeout.connect(timeout)
        self._timer.start(int(self.timeout))

    def showEvent(self, e):
        super().showEvent(e)
        if not e.isAccepted():
            return
        if self.animation.state() == QAbstractAnimation.Running:
            return
        self.setWindowOpacity(0.0)

        self.animation.setStartValue(0.0)
        self.animation.setEndValue(self.final_opacity)

        self.didShow.emit()
        self._cleanUp()
        self.animation.setDirection(QAbstractAnimation.Forward)
        self.animation.start()

        if isinstance(self.timeout, (float, int)) and self.timeout > 0:

            def autoHide():
                self._cleanUp()
                self._startTimer(self.hideAnimated)

            self.animation.finished.connect(autoHide)

    def hideEvent(self, e):
        super().hideEvent(e)
        if e.isAccepted():
            self._cleanUp()
            if self.delete_on_hide:
                self.setParent(None)
                self.deleteLater()

    def _disconnectFinished(self):
        try:
            self.animation.finished.disconnect()
        except:
            pass

    def hideAnimated(self):
        if self.animation.state() == QAbstractAnimation.Running:
            return
        self._cleanUp()
        self.animation.setDirection(QAbstractAnimation.Backward)
        self.animation.start()

        def doHide():
            self._cleanUp()
            self.hide()
            self.didHide.emit()

        self.animation.finished.connect(doHide)

    def eventFilter(self, obj, e):
        evts = (QEvent.Move, QEvent.Resize, QEvent.Close, QEvent.Hide,
                QEvent.Show)
        if self.activation_hides:
            evts = (*evts, QEvent.WindowStateChange, QEvent.WindowDeactivate)
        if e.type() in evts:
            # if the parent window is moved or otherwise touched, make this popup go away
            self.hideAnimated()
        return False

    def mousePressEvent(self, e):
        if e.button() == Qt.LeftButton:
            self.onClick.emit()
            e.accept()
        elif e.button() == Qt.RightButton:
            self.onRightClick.emit()
            e.accept()

    def _cleanUp(self):
        ''' Forces animation and timer to stop. This is essential to force
        the object into a known consistent state ready for deletion, restart
        of animations, etc. '''
        self._disconnectFinished()
        self._killTimer()
        self.animation.stop()
예제 #22
0
 def shouldDelete(self, elem: QPropertyAnimation):
     return elem.state() == QPropertyAnimation.Stopped
예제 #23
0
class MyWindow(QMainWindow, Ui_MainWindow):
    def __init__(self, s, parent=None):
        super(MyWindow, self).__init__(parent)
        self.setupUi(self)
        self.s = s
        # self.bursar_window = QDialog()
        self.bursar_window = Ui_Dialog()
        # self.bursar_dialog.setupUi(self.bursar_window)
        # main game items
        self.step = QtWidgets.QPushButton(self.centralwidget)
        self.step.setGeometry(QtCore.QRect(683, 140, 65, 56))
        self.step.setStyleSheet("border-image: url(:/figure/stepbott.png);")
        self.step.setText("")
        self.step.setObjectName("step")
        self.yelmoney = QtWidgets.QLabel(self.centralwidget)
        self.yelmoney.setGeometry(QtCore.QRect(240, 184, 71, 15))
        self.yelmoney.setStyleSheet("border-image: url(:/game/white.png);\n"
                                    "font: 15pt \"appo paint\";")
        self.yelmoney.setText("")
        self.yelmoney.setObjectName("yelmoney")
        self.yelcash = QtWidgets.QLabel(self.centralwidget)
        self.yelcash.setGeometry(QtCore.QRect(240, 205, 71, 15))
        self.yelcash.setStyleSheet("border-image: url(:/game/white.png);\n"
                                   "font: 15pt \"appo paint\";")
        self.yelcash.setText("")
        self.yelcash.setObjectName("yelcash")
        self.yelhouse = QtWidgets.QLabel(self.centralwidget)
        self.yelhouse.setGeometry(QtCore.QRect(240, 230, 71, 15))
        self.yelhouse.setStyleSheet("border-image: url(:/game/white.png);\n"
                                    "font: 15pt \"appo paint\";")
        self.yelhouse.setText("")
        self.yelhouse.setObjectName("yelhouse")
        self.yelname = QtWidgets.QLabel(self.centralwidget)
        self.yelname.setGeometry(QtCore.QRect(233, 156, 81, 21))
        self.yelname.setStyleSheet("border-image: url(:/game/white.png);\n"
                                   "font: 20pt \"appo paint\";")
        self.yelname.setText("")
        self.yelname.setObjectName("yelname")
        self.yelloan = QtWidgets.QLabel(self.centralwidget)
        self.yelloan.setGeometry(QtCore.QRect(240, 253, 71, 15))
        self.yelloan.setStyleSheet("border-image: url(:/game/white.png);\n"
                                   "font: 15pt \"appo paint\";")
        self.yelloan.setText("")
        self.yelloan.setObjectName("yelloan")

        self.bluehouse = QtWidgets.QLabel(self.centralwidget)
        self.bluehouse.setGeometry(QtCore.QRect(240, 401, 71, 15))
        self.bluehouse.setStyleSheet("border-image: url(:/game/white.png);\n"
                                     "font: 15pt \"appo paint\";")
        self.bluehouse.setText("")
        self.bluehouse.setObjectName("bluehouse")
        self.bluename = QtWidgets.QLabel(self.centralwidget)
        self.bluename.setGeometry(QtCore.QRect(231, 329, 81, 21))
        self.bluename.setStyleSheet("border-image: url(:/game/white.png);\n"
                                    "font: 20pt \"appo paint\";")
        self.bluename.setText("")
        self.bluename.setObjectName("bluename")
        self.bluecash = QtWidgets.QLabel(self.centralwidget)
        self.bluecash.setGeometry(QtCore.QRect(240, 377, 71, 15))
        self.bluecash.setStyleSheet("border-image: url(:/game/white.png);\n"
                                    "font: 15pt \"appo paint\";")
        self.bluecash.setText("")
        self.bluecash.setObjectName("bluecash")
        self.bluemoney = QtWidgets.QLabel(self.centralwidget)
        self.bluemoney.setGeometry(QtCore.QRect(240, 356, 71, 15))
        self.bluemoney.setStyleSheet("border-image: url(:/game/white.png);\n"
                                     "font: 15pt \"appo paint\";")
        self.bluemoney.setText("")
        self.bluemoney.setObjectName("bluemoney")

        self.blueloan = QtWidgets.QLabel(self.centralwidget)
        self.blueloan.setGeometry(QtCore.QRect(240, 425, 71, 15))
        self.blueloan.setStyleSheet("border-image: url(:/game/white.png);\n"
                                    "font: 15pt \"appo paint\";")
        self.blueloan.setText("")
        self.blueloan.setObjectName("blueloan")
        self.info = QtWidgets.QLabel(self.centralwidget)
        self.info.setGeometry(QtCore.QRect(370, 351, 451, 41))
        self.info.setStyleSheet("border-image: url(:/game/infoframe.png);\n"
                                "font: 18pt \"appo paint\"")
        self.info.setText("")
        self.info.setObjectName("info")
        self.buy_info = QtWidgets.QLabel(self.centralwidget)
        self.buy_info.setGeometry(QtCore.QRect(370, 390, 240, 71))
        self.buy_info.setStyleSheet(
            "border-image: url(:/game/infoframe.png);\n"
            "font: 18pt \"appo paint\"")
        self.buy_info.setText("")
        self.buy_info.setObjectName("buy_info")
        self.fate = QtWidgets.QLabel(self.centralwidget)
        self.fate.setGeometry(QtCore.QRect(370, 310, 451, 80))
        self.fate.setStyleSheet("border-image: url(:/game/infoframe.png);\n"
                                "font: 18pt \"appo paint\"")
        self.fate.setText("")
        self.fate.setObjectName("fate")
        self.stepnum = QtWidgets.QLabel(self.centralwidget)
        self.stepnum.setGeometry(QtCore.QRect(764, 142, 51, 51))
        self.stepnum.setStyleSheet("font: 40pt \"appo paint\";\n"
                                   "border-image: url(:/game/white.png);")
        self.stepnum.setText("Na")
        self.stepnum.setObjectName("stepnum")
        self.turn = QtWidgets.QLabel(self.centralwidget)
        self.turn.setGeometry(QtCore.QRect(764, 221, 51, 51))
        self.turn.setStyleSheet("font: 40pt \"appo paint\";\n"
                                "border-image: url(:/game/white.png);")
        self.turn.setText("1")
        self.turn.setObjectName("turn")

        self.player1 = Player(self.centralwidget)
        self.player1.set_name("alice")
        self.player1.initiate_color(1)
        self.player1.setGeometry(QtCore.QRect(10, 55, 41, 51))
        self.player1.setStyleSheet(
            "border-image: url(:/figure/yellowman.png);")
        self.player1.setText("")
        self.player1.setObjectName("player1")

        self.player2 = Player(self.centralwidget)
        self.player2.set_name("bob")
        self.player2.initiate_color(2)
        self.player2.setGeometry(QtCore.QRect(60, 55, 41, 51))
        self.player2.setStyleSheet("border-image: url(:/figure/blueman.png);")
        self.player2.setText("")
        self.player2.setObjectName("player2")

        self.yes = QtWidgets.QPushButton(self.centralwidget)
        self.yes.setGeometry(QtCore.QRect(650, 410, 71, 31))
        self.yes.setStyleSheet("border-image: url(:/figure/yes.png);")
        self.yes.setText("")
        self.yes.setObjectName("yes")

        self.no = QtWidgets.QPushButton(self.centralwidget)
        self.no.setGeometry(QtCore.QRect(750, 410, 71, 31))
        self.no.setStyleSheet("border-image: url(:/figure/no.png);")
        self.no.setText("")
        self.no.setObjectName("no")

        # main game variables
        self.bdposition = [[60, 55], [150, 55], [270, 55], [360,
                                                            55], [480, 55],
                           [580, 55], [680, 55], [780, 55], [900, 55],
                           [900, 140], [900, 235], [900, 335], [900, 445],
                           [900, 550], [780, 550], [680, 550], [580, 550],
                           [480, 550], [360, 550], [270, 550], [150, 550],
                           [60, 550], [60, 445], [60, 335], [60, 235],
                           [60, 150]]

        self.player_name1 = self.player1.name
        self.player_name2 = self.player2.name

        self.turn_count = 0

        #
        self.anim1 = QPropertyAnimation(self.player1, b"geometry")
        self.anim1.setDuration(1000)
        self.anim2 = QPropertyAnimation(self.player2, b"geometry")
        self.anim2.setDuration(1000)

        # buildings
        self.green_center = Building(self.centralwidget)
        self.green_center.setGeometry(QtCore.QRect(121, 105, 88, 15))
        self.green_center.setStyleSheet(
            "background-color: rgb(255, 255, 255);")
        self.green_center.setText("")
        self.green_center.setObjectName("green_center")
        self.public_safety = Building(self.centralwidget)
        self.public_safety.setGeometry(QtCore.QRect(209, 105, 103, 15))
        self.public_safety.setStyleSheet(
            "background-color: rgb(255, 255, 255);")
        self.public_safety.setText("")
        self.public_safety.setObjectName("public_safety")
        self.student_life = Building(self.centralwidget)
        self.student_life.setGeometry(QtCore.QRect(312, 105, 138, 15))
        self.student_life.setStyleSheet(
            "background-color: rgb(255, 255, 255);")
        self.student_life.setText("")
        self.student_life.setObjectName("student_life")
        self.Room110_Gallery = Building(self.centralwidget)
        self.Room110_Gallery.setGeometry(QtCore.QRect(450, 105, 103, 15))
        self.Room110_Gallery.setStyleSheet(
            "background-color: rgb(255, 255, 255);")
        self.Room110_Gallery.setText("")
        self.Room110_Gallery.setObjectName("Room110_Gallery")
        self.mail_room = Building(self.centralwidget)
        self.mail_room.setGeometry(QtCore.QRect(553, 105, 100, 15))
        self.mail_room.setStyleSheet("background-color: rgb(255, 255, 255);")
        self.mail_room.setText("")
        self.mail_room.setObjectName("mail_room")
        self.luckin = Building(self.centralwidget)
        self.luckin.setGeometry(QtCore.QRect(653, 105, 103, 15))
        self.luckin.setStyleSheet("background-color: rgb(255, 255, 255);")
        self.luckin.setText("")
        self.luckin.setObjectName("luckin")
        self.cafeteria = Building(self.centralwidget)
        self.cafeteria.setGeometry(QtCore.QRect(755, 105, 85, 15))
        self.cafeteria.setStyleSheet("background-color: rgb(255, 255, 255);")
        self.cafeteria.setText("")
        self.cafeteria.setObjectName("cafeteria")
        self.auditorium = Building(self.centralwidget)
        self.auditorium.setGeometry(QtCore.QRect(842, 200, 13, 92))
        self.auditorium.setStyleSheet("background-color: rgb(255, 255, 255);")
        self.auditorium.setText("")
        self.auditorium.setObjectName("auditorium")
        self.the_box = Building(self.centralwidget)
        self.the_box.setGeometry(QtCore.QRect(842, 120, 13, 80))
        self.the_box.setStyleSheet("background-color: rgb(255, 255, 255);")
        self.the_box.setText("")
        self.the_box.setObjectName("the_box")
        self.cafe = Building(self.centralwidget)
        self.cafe.setGeometry(QtCore.QRect(842, 292, 13, 92))
        self.cafe.setStyleSheet("background-color: rgb(255, 255, 255);")
        self.cafe.setText("")
        self.cafe.setObjectName("cafe")
        self.bursar = Building(self.centralwidget)
        self.bursar.setGeometry(QtCore.QRect(842, 384, 13, 92))
        self.bursar.setStyleSheet("background-color: rgb(255, 255, 255);")
        self.bursar.setText("")
        self.bursar.setObjectName("bursar")
        self.IT_center = Building(self.centralwidget)
        self.IT_center.setGeometry(QtCore.QRect(754, 480, 85, 15))
        self.IT_center.setStyleSheet("background-color: rgb(255, 255, 255);")
        self.IT_center.setText("")
        self.IT_center.setObjectName("IT_center")
        self.library = Building(self.centralwidget)
        self.library.setGeometry(QtCore.QRect(651, 480, 103, 15))
        self.library.setStyleSheet("background-color: rgb(255, 255, 255);")
        self.library.setText("")
        self.library.setObjectName("library")
        self.arc = Building(self.centralwidget)
        self.arc.setGeometry(QtCore.QRect(553, 480, 99, 15))
        self.arc.setStyleSheet("background-color: rgb(255, 255, 255);")
        self.arc.setText("")
        self.arc.setObjectName("arc")
        self.advisor_office = Building(self.centralwidget)
        self.advisor_office.setGeometry(QtCore.QRect(452, 480, 101, 15))
        self.advisor_office.setStyleSheet(
            "background-color: rgb(255, 255, 255);")
        self.advisor_office.setText("")
        self.advisor_office.setObjectName("adviser_office")
        self.H_W_center = Building(self.centralwidget)
        self.H_W_center.setGeometry(QtCore.QRect(348, 480, 104, 15))
        self.H_W_center.setStyleSheet("background-color: rgb(255, 255, 255);")
        self.H_W_center.setText("")
        self.H_W_center.setObjectName("H_W_center")
        self.CDC = Building(self.centralwidget)
        self.CDC.setGeometry(QtCore.QRect(208, 480, 140, 15))
        self.CDC.setStyleSheet("background-color: rgb(255, 255, 255);")
        self.CDC.setText("")
        self.CDC.setObjectName("CDC")
        self.mac_lab = Building(self.centralwidget)
        self.mac_lab.setGeometry(QtCore.QRect(106, 480, 102, 15))
        self.mac_lab.setStyleSheet("background-color: rgb(255, 255, 255);")
        self.mac_lab.setText("")
        self.mac_lab.setObjectName("mac_lab")
        self.ally_lounge = Building(self.centralwidget)
        self.ally_lounge.setGeometry(QtCore.QRect(0, 480, 106, 15))
        self.ally_lounge.setStyleSheet("background-color: rgb(255, 255, 255);")
        self.ally_lounge.setText("")
        self.ally_lounge.setObjectName("ally_lounge")
        self.fos_lab = Building(self.centralwidget)
        self.fos_lab.setGeometry(QtCore.QRect(105, 387, 15, 94))
        self.fos_lab.setStyleSheet("background-color: rgb(255, 255, 255);")
        self.fos_lab.setText("")
        self.fos_lab.setObjectName("fos_lab")
        self.piano_room = Building(self.centralwidget)
        self.piano_room.setGeometry(QtCore.QRect(105, 293, 15, 94))
        self.piano_room.setStyleSheet("background-color: rgb(255, 255, 255);")
        self.piano_room.setText("")
        self.piano_room.setObjectName("piano_room")
        self.ima_lab = Building(self.centralwidget)
        self.ima_lab.setGeometry(QtCore.QRect(105, 199, 15, 94))
        self.ima_lab.setStyleSheet("background-color: rgb(255, 255, 255);")
        self.ima_lab.setText("")
        self.ima_lab.setObjectName("ima_lab")
        self.f15 = Building(self.centralwidget)
        self.f15.setGeometry(QtCore.QRect(105, 122, 15, 77))
        self.f15.setStyleSheet("background-color: rgb(255, 255, 255);")
        self.f15.setText("")
        self.f15.setObjectName("f15")

        self.bdposition = [[60, 55], [150, 55], [270, 55], [360,
                                                            55], [480, 55],
                           [580, 55], [680, 55], [780, 55], [900, 55],
                           [900, 140], [900, 235], [900, 335], [900, 445],
                           [900, 550], [780, 550], [680, 550], [580, 550],
                           [480, 550], [360, 550], [270, 550], [150, 550],
                           [60, 550], [60, 425], [60, 335], [60, 235],
                           [60, 150]]
        self.building_dic = {
            (60, 55): None,
            (150, 55): self.green_center,
            (270, 55): self.public_safety,
            (360, 55): self.student_life,
            (480, 55): self.Room110_Gallery,
            (580, 55): self.mail_room,
            (680, 55): self.luckin,
            (780, 55): self.cafeteria,
            (900, 55): None,
            (900, 140): self.the_box,
            (900, 235): self.auditorium,
            (900, 335): self.cafe,
            (900, 445): self.bursar,
            (900, 550): None,
            (780, 550): self.IT_center,
            (680, 550): self.library,
            (580, 550): self.arc,
            (480, 550): self.advisor_office,
            (360, 550): self.H_W_center,
            (270, 550): self.CDC,
            (150, 550): self.mac_lab,
            (60, 550): self.ally_lounge,
            (60, 425): self.fos_lab,
            (60, 335): self.piano_room,
            (60, 235): self.ima_lab,
            (60, 150): self.f15
        }
        for u, v in self.building_dic.items():
            x, y = u
            if v is not None:
                v.x_position = x
                v.y_position = y
        # main game set up
        self.hide_main_game()
        self.connect_buttons()

    def turn(self):
        return self.player_name1 if self.turn_count % 2 == 0 else self.player_name2

    def setName1(self, name):
        self.player_name1 = name
        self.player1.name = name

    def setName2(self, name):
        self.player_name2 = name
        self.player2.name = name

    def hide_cover(self):
        self.exit.hide()
        self.play.hide()

    def show_cover(self):
        self.exit.show()
        self.play.show()

    def hide_main_game(self):
        self.step.hide()
        self.turn.hide()
        self.yelcash.hide()
        self.yelmoney.hide()
        self.yelname.hide()
        self.yelhouse.hide()
        self.bluecash.hide()
        self.bluehouse.hide()
        self.bluemoney.hide()
        self.bluename.hide()
        self.info.hide()
        self.stepnum.hide()
        self.player1.hide()
        self.player2.hide()
        for v in self.building_dic.values():
            if v is not None:
                v.hide()
        self.yes.hide()
        self.no.hide()
        self.buy_info.hide()
        self.fate.hide()

    def set_player1_info(self):
        self.yelname.setText(str(self.player1.name))
        self.yelcash.setText(str(int(self.player1.cash)))
        self.yelmoney.setText(str(int(self.player1.get_money())))
        self.yelhouse.setText(str(int(self.player1.get_house())))
        self.yelloan.setText(str(int(self.player1.loaned_money)))

    def set_player2_info(self):
        self.bluename.setText(str(self.player2.name))
        self.bluecash.setText(str(int(self.player2.cash)))
        self.bluemoney.setText(str(int(self.player2.get_money())))
        self.bluehouse.setText(str(int(self.player2.get_house())))
        self.blueloan.setText(str(int(self.player2.loaned_money)))

    def show_main_game(self):
        self.set_player1_info()
        self.set_player2_info()
        self.step.show()
        self.turn.show()
        self.yelcash.show()
        self.yelmoney.show()
        self.yelname.show()
        self.yelhouse.show()
        self.bluecash.show()
        self.bluehouse.show()
        self.bluemoney.show()
        self.bluename.show()
        self.info.show()
        self.stepnum.show()
        self.player1.show()
        self.player2.show()
        for v in self.building_dic.values():
            if v is not None:
                v.show()
        # self.yes.show()
        # self.no.show()
        self.buy_info.show()
        self.fate.show()

    def connect_buttons(self):
        self.play.clicked.connect(self.start)
        self.step.clicked.connect(self.roll)
        self.exit.clicked.connect(self.end)

    def start(self):
        d = {"action": "gaming", "update": "start"}
        mysend(self.s, json.dumps(d))
        self.graphicsView.setStyleSheet(
            "border-image: url(:/figure/life_in_NYUSH_v2.jpg);")
        self.hide_cover()
        self.show_main_game()
        # self.bursar_window.show()
        # self.repaint()

    def roll(self):
        self.fate.hide()
        if self.anim1.state() != self.anim1.Running and self.anim2.state(
        ) != self.anim2.Running:
            num = random.randint(1, 6)
            # num = 6
            if self.turn_count % 2 == 0:
                curr_x, curr_y = self.bdposition[self.player1.count]
                next_count = (self.player1.count + num) % 26
                bankrupt = self.player1.bankrupt()
                if next_count < self.player1.count:
                    if bankrupt:
                        self.info.setText("{} bankrupt, {} wins.".format(
                            self.player1.name, self.player2.name))
                        self.info.show()
                        self.yes.clicked.connect(self.end)
                        self.yes.show()
                    else:
                        success = self.player1.pay_debt()
                        if success is not None:
                            if success:
                                self.fate.setText(
                                    "Successfully pay back you debt.")
                            else:
                                self.fate.setText(
                                    "No enough money to pay your debt")
                            self.fate.show()
                            self.set_player1_info()
                            self.set_player2_info()
                else:
                    bankrupt = False
                if not bankrupt:
                    next_x, next_y = self.bdposition[next_count]
                    self.stepnum.setText("{}".format(num))
                    self.player1.count = next_count
                    self.anim1.setStartValue(QRect(curr_x, curr_y, 41, 51))
                    self.anim1.setEndValue(QRect(next_x, next_y, 41, 51))
                    self.anim1.start()
                    self.pass_building(self.player1, next_x, next_y)
            else:
                curr_x, curr_y = self.bdposition[self.player2.count]
                next_count = (self.player2.count + num) % 26
                bankrupt = self.player2.bankrupt()
                if next_count < self.player2.count:
                    if bankrupt:
                        self.info.setText("{} bankrupt, {} wins.".format(
                            self.player2.name, self.player1.name))
                        self.info.show()
                        self.yes.clicked.connect(self.end)
                        self.yes.show()
                    else:
                        success = self.player2.pay_debt()
                        if success is not None:
                            if success:
                                self.fate.setText(
                                    "Successfully pay back you debt.")
                            else:
                                self.fate.setText(
                                    "No enough money to pay your debt")
                            self.fate.show()
                            self.set_player1_info()
                            self.set_player2_info()
                else:
                    bankrupt = False
                if not bankrupt:
                    next_x, next_y = self.bdposition[next_count]
                    self.stepnum.setText("{}".format(num))
                    self.player2.count = next_count
                    self.anim2.setStartValue(QRect(curr_x, curr_y, 41, 51))
                    self.anim2.setEndValue(QRect(next_x, next_y, 41, 51))
                    self.anim2.start()
                    self.pass_building(self.player2, next_x, next_y)

            self.step.setEnabled(False)
            d = {"action": "gaming", "update": "roll", "num": num}
            mysend(self.s, json.dumps(d))
            self.turn.setText("{}".format(self.turn_count // 2 + 1))
            self.turn_count += 1

    def pass_building(self, player, x, y):
        assert isinstance(player, Player)
        if player.name == self.player_name1:
            other = self.player2
        else:
            other = self.player1
        building = self.building_dic[(x, y)]
        # self.fate.setText("")
        self.info.setText("")
        self.buy_info.setText("")
        if building is not None:
            # fate part
            if building.objectName() == "bursar":
                self.bursar_window.show()
                self.bursar_window.set_info_text(player.get_max_loan(),
                                                 player.get_money())
                # player.cash += 1000
                # self.fate.setText("Get funded by bursar.")
                self.yes.show()
                self.yes.clicked.connect(lambda: self.finish_loan(player))
                self.buy_info.setText("Click here to finish loan.")
                self.buy_info.show()
            # other fates here
            elif building.objectName() == "CDC":
                chance, money = self.chance(player)
                d = {
                    "action": "gaming",
                    "update": "passing_building",
                    "x": x,
                    "y": y,
                    "chance": chance,
                    "money": money,
                    "player": 1 if player.name == self.player1.name else 2
                }
                mysend(self.s, json.dumps(d))
                self.fate.setText(chance)
                self.fate.show()
                self.yes.show()
                self.yes.clicked.connect(self.confirm)
            elif building.objectName() == "student_life":
                destiny, money = self.destiny(player)
                d = {
                    "action": "gaming",
                    "update": "passing_building",
                    "x": x,
                    "y": y,
                    "destiny": destiny,
                    "money": money,
                    "player": 1 if player.name == self.player1.name else 2
                }
                mysend(self.s, json.dumps(d))
                self.fate.setText(destiny)
                self.fate.show()
                self.yes.show()
                self.yes.clicked.connect(self.confirm)
            # update once after fate.

            # buy land
            # if building.objectName() not in ["bursar", "CDC", "student_life"]:
            else:
                # self.fate.setText("")
                if building.owner is None:
                    building_name = building.objectName()
                    self.info.setText(
                        "You are passing {0}.".format(building_name))
                    self.buy_info.setText("Do you want to buy?")
                    self.yes.clicked.connect(
                        lambda: self.buy(player, building))
                    self.no.clicked.connect(
                        lambda: self.reject_buy(x, y, player))
                    self.buy_info.show()
                    self.info.show()
                    self.yes.show()
                    self.no.show()

                # passing others' building: fined
                elif player.name != building.owner:
                    fined_money = player.fine_money(building.level)
                    d = {
                        "action": "gaming",
                        "update": "passing_building",
                        "x": x,
                        "y": y,
                        "player": 1 if player.name == self.player1.name else 2
                    }
                    mysend(self.s, json.dumps(d))
                    other.cash += fined_money
                    self.info.setText(
                        "You are passing others building, fined ${}.".format(
                            fined_money))
                    self.info.show()
                    self.yes.show()
                    self.yes.clicked.connect(self.confirm)
                    # self.step.setEnabled(True)
                    # print(self.step.isEnabled())
                    # self.step.repaint()
                    # print(self.step.isEnabled())

                # passing my building: upgrade
                elif player.name == building.owner:
                    self.info.setText("You are passing your own building.")
                    self.buy_info.setText("Do you want to upgrade?")
                    self.buy_info.show()
                    self.info.show()
                    self.yes.clicked.connect(
                        lambda: self.buy(player, building))
                    self.no.clicked.connect(
                        lambda: self.reject_buy(x, y, player))
                    self.yes.show()
                    self.no.show()

            self.set_player1_info()
            self.set_player2_info()
        else:
            d = {
                "action": "gaming",
                "update": "passing_building",
                "x": x,
                "y": y,
                "player": 1 if player.name == self.player1.name else 2
            }
            mysend(self.s, json.dumps(d))
            self.info.setText("No buildings to buy here.")
            self.info.show()
            self.yes.show()
            self.yes.clicked.connect(self.confirm)

    def pass_building_update(self, player, x, y, msg):
        assert isinstance(player, Player)
        if player.name == self.player_name1:
            other = self.player2
        else:
            other = self.player1
        building = self.building_dic[(x, y)]
        self.fate.setText("")
        self.info.setText("")
        self.buy_info.setText("")
        if building is not None:
            # fate part
            if building.objectName() == "bursar":
                loan_result = msg["loan"]
                if loan_result is not None:
                    self.fate.setText(
                        "Others have successfully loan ${}.".format(
                            loan_result))
                    self.fate.show()
                    player.loan_money(loan_result)
                    player.cash += loan_result
                else:
                    self.fate.setText(
                        "The amount others claim exceeds the \nlimit he can loan."
                    )
                    self.fate.show()

            # other fates here
            elif building.objectName() == "CDC":
                chance = msg["chance"]
                earn = msg["money"]
                self.fate.setText(chance)
                self.fate.show()
                player.cash += earn

            elif building.objectName() == "student_life":
                destiny = msg["destiny"]
                lost = msg["money"]
                self.fate.setText(destiny)
                self.fate.show()
                player.fine_money(level=None, money=lost)
            # update once after fate.

            # buy land
            # if building.objectName() not in ["bursar", "CDC", "student_life"]:
            else:
                # print(building.owner, player.name, msg)

                if building.owner is None:
                    building_name = building.objectName()
                    if msg["buy"]:
                        try:
                            player.buy_building(building)
                            self.info.setText(
                                "Others choose to buy {0}.".format(
                                    building_name))
                            self.set_player1_info()
                            self.set_player2_info()
                        except ValueError:
                            self.info.setText("No enough money to buy.")
                    else:
                        self.info.setText(
                            "Others choose not to buy {0}".format(
                                building_name))
                    self.info.show()
                # passing others' building: fined
                elif player.name != building.owner:
                    fined_money = player.fine_money(building.level)
                    other.cash += fined_money
                    self.info.setText(
                        "Others are passing your building, get ${}.".format(
                            fined_money))
                    self.info.show()

                # passing my building: upgrade
                elif player.name == building.owner:
                    if msg["buy"]:
                        try:
                            player.buy_building(building)
                            self.info.setText("Others choose to upgrade.")
                            self.set_player1_info()
                            self.set_player2_info()
                        except ValueError:
                            self.info.setText("No enough money to buy.")
                    else:
                        self.info.setText("Other chooses not to upgrade.")
                    self.info.show()

            self.set_player1_info()
            self.set_player2_info()
        else:
            self.info.setText("No buildings to buy here.")
            self.info.show()

        self.step.setEnabled(True)

    def buy(self, player, building):
        d = {
            "action": "gaming",
            "update": "passing_building",
            "x": building.x_position,
            "y": building.y_position,
            "buy": True,
            "player": 1 if player.name == self.player1.name else 2
        }
        mysend(self.s, json.dumps(d))
        assert isinstance(player, Player)
        assert isinstance(building, Building)
        try:
            player.buy_building(building)
            self.info.hide()
            self.set_player1_info()
            self.set_player2_info()
        except ValueError:
            self.info.setText("No enough money to buy.")
        self.yes.disconnect()
        self.yes.hide()
        self.no.hide()
        self.no.disconnect()
        self.buy_info.hide()
        self.fate.hide()

    def confirm(self):
        self.fate.hide()
        self.fate.setText("")
        self.yes.hide()
        self.no.hide()
        self.yes.disconnect()
        self.buy_info.hide()
        self.info.hide()

    def reject_buy(self, x, y, player):
        d = {
            "action": "gaming",
            "update": "passing_building",
            "x": x,
            "y": y,
            "buy": False,
            "player": 1 if player.name == self.player1.name else 2
        }
        mysend(self.s, json.dumps(d))
        self.fate.hide()
        self.fate.setText("")
        self.yes.hide()
        self.no.hide()
        self.yes.disconnect()
        self.no.disconnect()
        self.buy_info.hide()
        self.info.hide()

    def finish_loan(self, player):
        assert isinstance(player, Player)
        loan_result = self.bursar_window.result
        if loan_result is not None:
            self.fate.setText(
                "You have successfully loan ${}.".format(loan_result))
            self.fate.show()
            player.loan_money(loan_result)
            player.cash += loan_result
        else:
            self.fate.setText(
                "The amount you claim exceeds the \nlimit you can loan.")
            self.fate.show()
        self.set_player1_info()
        self.set_player2_info()
        self.yes.hide()
        self.no.hide()
        self.yes.disconnect()
        self.buy_info.hide()
        self.info.hide()
        d = {
            "action": "gaming",
            "update": "passing_building",
            "x": 900,
            "y": 445,
            "loan": loan_result,
            "player": 1 if player.name == self.player1.name else 2
        }
        mysend(self.s, json.dumps(d))

    def destiny(self, player):
        assert isinstance(player, Player)
        # list_destiny = [['You need to go to the ARC to revise your essay.', 2],
        # ['You find hair in your meal and decide to go to Health & Wellness for psychological relief.',
        #  1],
        # ['You were reported for your behavior when participating the student union election.', 1],
        # ['You need to go to the eastern-oasis for military training.', 2],
        # ['You were asked to participate in the graduation ceremony at the Oriental Pearl Tower.', 1],
        # ['You plan to practice your piano at the piano room.', 1],
        # ['You plan to buy luck-in coffee.', 1],
        # ['You were collapsed by the smell of the moor besom in front of AB.', 1],
        list_destiny = [
            [
                'Your stuff in 314 has been removed \nand lost, you lost $2000.',
                2000
            ], ['You are informed to pay \ntuition fee for $3000.', 3000],
            [
                'You bought Mate Tea for $2000 during \nGPS to get rid of sleepiness.',
                2000
            ],
            [
                'You missed shuttle and get a \ntaxi back to the dorm for $5000.',
                5000
            ], ['You bought bubble tea for $1000.', 1000],
            ['You purchased textbook for $5000.', 5000],
            [
                'You lost your campus card,  \nyou have to go to Public Safety \nto replace it for $5000.',
                5000
            ],
            [
                'You bought tickets and clothes \nfor Spring Formal for $1000.',
                1000
            ]
        ]
        chosen_destiny = random.choice(list_destiny)
        lost = chosen_destiny[1]
        player.fine_money(level=None, money=lost)
        return tuple(chosen_destiny)

    def chance(self, player):
        assert isinstance(player, Player)
        list_chance = [
            [
                'You have been offered for the position of Residence-hall Assistant\nand get payment for $3000!',
                3000
            ],
            [
                'You have been recommended an internship by the professor\nand get payment for $2000!',
                2000
            ], ['You get the tuition-fee refund for $2000!', 2000],
            [
                'You have been offered for the position of Orientation Ambassador\nand get payment for $1500!',
                1500
            ],
            [
                'You have been offered for the position of researching assistant\nand get payment for $1000!',
                1000
            ],
            [
                'You have been offered a on-campus job and get payment for $1000!',
                1000
            ], ['You win the prize of $1000 by taking a survey!', 1000],
            [
                'You participate in an event and get free lunch of $500 in return!',
                5000
            ], ['You get additional $5000 voucher from Starbucks!', 5000]
        ]
        chosen_chance = random.choice(list_chance)
        earn = chosen_chance[1]
        player.cash += earn
        return tuple(chosen_chance)

    def update_board(self, msg):
        if msg["update"] == "roll":
            num = msg["num"]
            if self.turn_count % 2 == 0:
                curr_x, curr_y = self.bdposition[self.player1.count]
                next_count = (self.player1.count + num) % 26
                bankrupt = self.player1.bankrupt()
                if next_count < self.player1.count:
                    if bankrupt:
                        self.info.setText("{} bankrupt, {} wins.".format(
                            self.player1.name, self.player2.name))
                        self.info.show()
                        self.yes.clicked.connect(self.end)
                        self.yes.show()
                    else:
                        success = self.player1.pay_debt()
                        if success is not None:
                            if success:
                                self.fate.setText(
                                    "{} successfully pays back his debt.".
                                    format(self.player1.name))
                            else:
                                self.fate.setText(
                                    "{} has no enough money to pay debt.".
                                    format(self.player1.name))
                            self.fate.show()
                            self.set_player1_info()
                            self.set_player2_info()
                else:
                    bankrupt = False
                if not bankrupt:
                    next_x, next_y = self.bdposition[next_count]
                    self.stepnum.setText("{}".format(num))
                    self.player1.count = next_count
                    self.anim1.setStartValue(QRect(curr_x, curr_y, 41, 51))
                    self.anim1.setEndValue(QRect(next_x, next_y, 41, 51))
                    self.anim1.start()
            else:
                curr_x, curr_y = self.bdposition[self.player2.count]
                next_count = (self.player2.count + num) % 26
                # pay debt and check bankrupt
                bankrupt = self.player2.bankrupt()
                if next_count < self.player2.count:
                    if bankrupt:
                        self.info.setText("{} bankrupt, {} wins.".format(
                            self.player2.name, self.player1.name))
                        self.info.show()
                        self.yes.clicked.connect(self.end)
                        self.yes.show()
                    else:
                        success = self.player2.pay_debt()
                        if success is not None:
                            if success:
                                self.fate.setText(
                                    "{} successfully pays back his debt.".
                                    format(self.player2.name))
                            else:
                                self.fate.setText(
                                    "{} has no enough money to pay debt.".
                                    format(self.player2.name))
                            self.fate.show()
                            self.set_player1_info()
                            self.set_player2_info()
                else:
                    bankrupt = False

                if not bankrupt:
                    next_x, next_y = self.bdposition[next_count]
                    self.stepnum.setText("{}".format(num))
                    self.player2.count = next_count
                    self.anim2.setStartValue(QRect(curr_x, curr_y, 41, 51))
                    self.anim2.setEndValue(QRect(next_x, next_y, 41, 51))
                    self.anim2.start()
            self.turn.setText("{}".format(self.turn_count // 2 + 1))
            self.turn_count += 1
        elif msg["update"] == "start":
            self.graphicsView.setStyleSheet(
                "border-image: url(:/figure/life_in_NYUSH_v2.jpg);")
            self.hide_cover()
            self.show_main_game()
            self.step.setEnabled(False)

        elif msg["update"] == "stop":
            self.hide()

        elif msg["update"] == "passing_building":
            # print("I am here passing_building")
            # print(msg)
            if msg["player"] == 1:
                player = self.player1
            else:
                player = self.player2
            x = msg["x"]
            y = msg["y"]
            self.pass_building_update(player, x, y, msg)
            self.step.setEnabled(True)

    def end(self):
        # d = {"action": "gaming", "update": "stop"}
        # mysend(self.s, json.dumps(d))
        self.close()
        self.hide()
예제 #24
0
class ScatterDataModifier(QObject):

    shadowQualityChanged = pyqtSignal()

    def __init__(self, scatter):
        super(ScatterDataModifier, self).__init__()

        self.m_graph = scatter
        self.m_inputHandler = CustomInputHandler()

        self.m_graph.activeTheme().setType(Q3DTheme.ThemeDigia)
        self.m_graph.setShadowQuality(QAbstract3DGraph.ShadowQualityMedium)
        self.m_graph.scene().activeCamera().setCameraPreset(
            Q3DCamera.CameraPresetFront)

        self.m_graph.setAxisX(QValue3DAxis())
        self.m_graph.setAxisY(QValue3DAxis())
        self.m_graph.setAxisZ(QValue3DAxis())

        self.m_graph.axisX().setRange(-10.0, 10.0)
        self.m_graph.axisY().setRange(-5.0, 5.0)
        self.m_graph.axisZ().setRange(-5.0, 5.0)

        series = QScatter3DSeries()
        series.setItemLabelFormat("@xLabel, @yLabel, @zLabel")
        series.setMesh(QAbstract3DSeries.MeshCube)
        series.setItemSize(0.15)
        self.m_graph.addSeries(series)

        self.m_animationCameraX = QPropertyAnimation(
            self.m_graph.scene().activeCamera(), 'xRotation')
        self.m_animationCameraX.setDuration(20000)
        self.m_animationCameraX.setStartValue(0.0)
        self.m_animationCameraX.setEndValue(360.0)
        self.m_animationCameraX.setLoopCount(-1)

        upAnimation = QPropertyAnimation(self.m_graph.scene().activeCamera(),
                                         'yRotation')
        upAnimation.setDuration(9000)
        upAnimation.setStartValue(5.0)
        upAnimation.setEndValue(45.0)

        downAnimation = QPropertyAnimation(self.m_graph.scene().activeCamera(),
                                           'yRotation')
        downAnimation.setDuration(9000)
        downAnimation.setStartValue(45.0)
        downAnimation.setEndValue(5.0)

        self.m_animationCameraY = QSequentialAnimationGroup()
        self.m_animationCameraY.setLoopCount(-1)
        self.m_animationCameraY.addAnimation(upAnimation)
        self.m_animationCameraY.addAnimation(downAnimation)

        self.m_animationCameraX.start()
        self.m_animationCameraY.start()

        self.m_graph.setActiveInputHandler(self.m_inputHandler)

        self.m_selectionTimer = QTimer()
        self.m_selectionTimer.setInterval(10)
        self.m_selectionTimer.timeout.connect(self.triggerSelection)
        self.m_selectionTimer.start()

    def start(self):
        self.addData()

    def addData(self):
        dataArray = []

        stream = QTextStream()
        dataFile = QFile(QFileInfo(__file__).absolutePath() + '/data.txt')
        if dataFile.open(QIODevice.ReadOnly | QIODevice.Text):
            stream.setDevice(dataFile)
            while not stream.atEnd():
                line = stream.readLine()
                if line.startswith('#'):
                    continue

                strList = line.split(',')
                # Each line has three data items: xPos, yPos and zPos values.
                if len(strList) < 3:
                    continue

                position = QVector3D(float(strList[0]), float(strList[1]),
                                     float(strList[2]))
                dataArray.append(QScatterDataItem(position))

        self.m_graph.seriesList()[0].dataProxy().resetArray(dataArray)

    def toggleCameraAnimation(self):
        if self.m_animationCameraX.state() != QAbstractAnimation.Paused:
            self.m_animationCameraX.pause()
            self.m_animationCameraY.pause()
        else:
            self.m_animationCameraX.resume()
            self.m_animationCameraY.resume()

    def triggerSelection(self):
        self.m_graph.scene().setSelectionQueryPosition(
            self.m_inputHandler.inputPosition())

    def shadowQualityUpdatedByVisual(self, sq):
        self.shadowQualityChanged.emit(int(sq))

    def changeShadowQuality(self, quality):
        self.m_graph.setShadowQuality(QAbstract3DGraph.ShadowQuality(quality))
예제 #25
0
class AnimatedToggle(QCheckBox):
    _transparent_pen = QPen(Qt.transparent)
    _light_grey_pen = QPen(Qt.lightGray)

    def __init__(self,
                 parent=None,
                 bar_color=Qt.gray,
                 checked_color="#00B0FF",
                 handle_color=Qt.white,
                 pulse_unchecked_color="#44999999",
                 pulse_checked_color="#4400B0EE"
                 ):
        super().__init__(parent)

        # Save our properties on the object via self, so we can access them later
        # in the paintEvent.
        self._bar_brush = QBrush(bar_color)
        self._bar_checked_brush = QBrush(QColor(checked_color).lighter())

        self._handle_brush = QBrush(handle_color)
        self._handle_checked_brush = QBrush(QColor(checked_color))

        self._pulse_unchecked_animation = QBrush(QColor(pulse_unchecked_color))
        self._pulse_checked_animation = QBrush(QColor(pulse_checked_color))

        # Setup the rest of the widget.
        self.setContentsMargins(8, 0, 8, 0)
        self._handle_position = 0

        self._pulse_radius = 0

        self.animation = QPropertyAnimation(self, b"handle_position", self)
        self.animation.setEasingCurve(QEasingCurve.InOutCubic)
        self.animation.setDuration(200)  # time in ms

        self.pulse_anim = QPropertyAnimation(self, b"pulse_radius", self)
        self.pulse_anim.setDuration(350)  # time in ms
        self.pulse_anim.setStartValue(10)
        self.pulse_anim.setEndValue(20)

        self.animations_group = QSequentialAnimationGroup()
        self.animations_group.addAnimation(self.animation)
        self.animations_group.addAnimation(self.pulse_anim)

        self.stateChanged.connect(self.setup_animation)

    def sizeHint(self):
        return QSize(58, 45)

    def hitButton(self, pos: QPoint):
        return self.contentsRect().contains(pos)

    @pyqtSlot(int)
    def setup_animation(self, value):
        self.animations_group.stop()
        if value:
            self.animation.setEndValue(1)
        else:
            self.animation.setEndValue(0)
        self.animations_group.start()

    def paintEvent(self, e: QPaintEvent):

        contRect = self.contentsRect()
        handleRadius = round(0.24 * contRect.height())

        p = QPainter(self)
        p.setRenderHint(QPainter.Antialiasing)

        p.setPen(self._transparent_pen)
        barRect = QRectF(
            0, 0,
            contRect.width() - handleRadius, 0.40 * contRect.height()
        )
        barRect.moveCenter(contRect.center())
        rounding = barRect.height() / 2

        # the handle will move along this line
        trailLength = contRect.width() - 2 * handleRadius

        xPos = contRect.x() + handleRadius + trailLength * self._handle_position

        if self.pulse_anim.state() == QPropertyAnimation.Running:
            p.setBrush(
                self._pulse_checked_animation if
                self.isChecked() else self._pulse_unchecked_animation)
            p.drawEllipse(QPointF(xPos, barRect.center().y()),
                          self._pulse_radius, self._pulse_radius)

        if self.isChecked():
            p.setBrush(self._bar_checked_brush)
            p.drawRoundedRect(barRect, rounding, rounding)
            p.setBrush(self._handle_checked_brush)

        else:
            p.setBrush(self._bar_brush)
            p.drawRoundedRect(barRect, rounding, rounding)
            p.setPen(self._light_grey_pen)
            p.setBrush(self._handle_brush)

        p.drawEllipse(
            QPointF(xPos, barRect.center().y()),
            handleRadius, handleRadius)

        p.end()

    @pyqtProperty(float)
    def handle_position(self):
        return self._handle_position

    @handle_position.setter
    def handle_position(self, pos):
        """change the property
        we need to trigger QWidget.update() method, either by:
            1- calling it here [ what we doing ].
            2- connecting the QPropertyAnimation.valueChanged() signal to it.
        """
        self._handle_position = pos
        self.update()

    @pyqtProperty(float)
    def pulse_radius(self):
        return self._pulse_radius

    @pulse_radius.setter
    def pulse_radius(self, pos):
        self._pulse_radius = pos
        self.update()
예제 #26
0
class NodeBodyItem(GraphicsPathObject):
    """
    The central part (body) of the `NodeItem`.
    """
    def __init__(self, parent=None):
        GraphicsPathObject.__init__(self, parent)
        assert(isinstance(parent, NodeItem))

        self.__processingState = 0
        self.__progress = -1
        self.__animationEnabled = False
        self.__isSelected = False
        self.__hasFocus = False
        self.__hover = False
        self.__shapeRect = QRectF(-10, -10, 20, 20)

        self.setAcceptHoverEvents(True)

        self.setFlag(QGraphicsItem.ItemSendsScenePositionChanges, True)
        self.setFlag(QGraphicsItem.ItemSendsGeometryChanges, True)

        self.setPen(QPen(Qt.NoPen))

        self.setPalette(default_palette())

        self.shadow = QGraphicsDropShadowEffect(
            blurRadius=3,
            color=QColor(SHADOW_COLOR),
            offset=QPointF(0, 0),
            )

        self.setGraphicsEffect(self.shadow)
        self.shadow.setEnabled(True)

        self.__blurAnimation = QPropertyAnimation(self.shadow, b"blurRadius",
                                                  self)
        self.__blurAnimation.setDuration(100)
        self.__blurAnimation.finished.connect(self.__on_finished)

        self.__pingAnimation = QPropertyAnimation(self, b"scale", self)
        self.__pingAnimation.setDuration(250)
        self.__pingAnimation.setKeyValues([(0.0, 1.0), (0.5, 1.1), (1.0, 1.0)])

    # TODO: The body item should allow the setting of arbitrary painter
    # paths (for instance rounded rect, ...)
    def setShapeRect(self, rect):
        """
        Set the item's shape `rect`. The item should be confined within
        this rect.

        """
        path = QPainterPath()
        path.addEllipse(rect)
        self.setPath(path)
        self.__shapeRect = rect

    def setPalette(self, palette):
        """
        Set the body color palette (:class:`QPalette`).
        """
        self.palette = palette
        self.__updateBrush()

    def setAnimationEnabled(self, enabled):
        """
        Set the node animation enabled.
        """
        if self.__animationEnabled != enabled:
            self.__animationEnabled = enabled

    def setProcessingState(self, state):
        """
        Set the processing state of the node.
        """
        if self.__processingState != state:
            self.__processingState = state
            if not state and self.__animationEnabled:
                self.ping()

    def setProgress(self, progress):
        """
        Set the progress indicator state of the node. `progress` should
        be a number between 0 and 100.

        """
        self.__progress = progress
        self.update()

    def ping(self):
        """
        Trigger a 'ping' animation.
        """
        animation_restart(self.__pingAnimation)

    def hoverEnterEvent(self, event):
        self.__hover = True
        self.__updateShadowState()
        return GraphicsPathObject.hoverEnterEvent(self, event)

    def hoverLeaveEvent(self, event):
        self.__hover = False
        self.__updateShadowState()
        return GraphicsPathObject.hoverLeaveEvent(self, event)

    def paint(self, painter, option, widget):
        """
        Paint the shape and a progress meter.
        """
        # Let the default implementation draw the shape
        if option.state & QStyle.State_Selected:
            # Prevent the default bounding rect selection indicator.
            option.state = option.state ^ QStyle.State_Selected
        GraphicsPathObject.paint(self, painter, option, widget)
        if self.__progress >= 0:
            # Draw the progress meter over the shape.
            # Set the clip to shape so the meter does not overflow the shape.
            painter.setClipPath(self.shape(), Qt.ReplaceClip)
            color = self.palette.color(QPalette.ButtonText)
            pen = QPen(color, 5)
            painter.save()
            painter.setPen(pen)
            painter.setRenderHints(QPainter.Antialiasing)
            span = max(1, int(self.__progress * 57.60))
            painter.drawArc(self.__shapeRect, 90 * 16, -span)
            painter.restore()

    def __updateShadowState(self):
        if self.__hasFocus:
            color = QColor(FOCUS_OUTLINE_COLOR)
            self.setPen(QPen(color, 1.5))
        else:
            self.setPen(QPen(Qt.NoPen))

        radius = 3
        enabled = False

        if self.__isSelected:
            enabled = True
            radius = 7

        if self.__hover:
            radius = 17
            enabled = True

        if enabled and not self.shadow.isEnabled():
            self.shadow.setEnabled(enabled)

        if self.__animationEnabled:
            if self.__blurAnimation.state() == QPropertyAnimation.Running:
                self.__blurAnimation.pause()

            self.__blurAnimation.setStartValue(self.shadow.blurRadius())
            self.__blurAnimation.setEndValue(radius)
            self.__blurAnimation.start()
        else:
            self.shadow.setBlurRadius(radius)

    def __updateBrush(self):
        palette = self.palette
        if self.__isSelected:
            cg = QPalette.Active
        else:
            cg = QPalette.Inactive

        palette.setCurrentColorGroup(cg)
        c1 = palette.color(QPalette.Light)
        c2 = palette.color(QPalette.Button)
        grad = radial_gradient(c2, c1)
        self.setBrush(QBrush(grad))

    # TODO: The selected and focus states should be set using the
    # QStyle flags (State_Selected. State_HasFocus)

    def setSelected(self, selected):
        """
        Set the `selected` state.

        .. note:: The item does not have `QGraphicsItem.ItemIsSelectable` flag.
                  This property is instead controlled by the parent NodeItem.

        """
        self.__isSelected = selected
        self.__updateBrush()

    def setHasFocus(self, focus):
        """
        Set the `has focus` state.

        .. note:: The item does not have `QGraphicsItem.ItemIsFocusable` flag.
                  This property is instead controlled by the parent NodeItem.

        """
        self.__hasFocus = focus
        self.__updateShadowState()

    def __on_finished(self):
        if self.shadow.blurRadius() == 0:
            self.shadow.setEnabled(False)