Пример #1
0
 def showErrorAnimation(self):
     error_group = QParallelAnimationGroup()
     for i in range(1, 9):
         self.animation.set_to_vibrate(self.keyDisplays.button(i),
                                       amp=10,
                                       direction=90 + 180 * (i % 2))
         error_group.addAnimation(self.animation.current_anim)
     self.animation.current_anim = error_group
     self.animation.current_anim.start(QPropertyAnimation.DeleteWhenStopped)
     self.animation.current_anim.finished.connect(self.clearPassword)
Пример #2
0
    def run_execution_leave_animation(self, skipped):
        """
        Starts the animation associated with execution leaving the icon.

        Args:
            skipped (bool): True if project item was not actually executed.
        """
        animation_group = QParallelAnimationGroup(self._toolbox)
        for link in self.outgoing_links():
            animation_group.addAnimation(
                link.make_execution_animation(skipped))
        animation_group.start()
Пример #3
0
    def make_execution_leave_animation(self):
        """
        Returns animation to play when execution leaves this item.

        Returns:
            QParallelAnimationGroup
        """
        icon = self.get_icon()
        links = set(link for conn in icon.connectors.values()
                    for link in conn.links if link.src_connector == conn)
        anim_group = QParallelAnimationGroup(self)
        for link in links:
            anim_group.addAnimation(link.make_execution_animation())
        return anim_group
Пример #4
0
    def _make_execution_leave_animation(self, item_name):
        """
        Returns animation to play when execution leaves this item.

        Returns:
            QParallelAnimationGroup
        """
        item = self._project_item_model.get_item(item_name).project_item
        icon = item.get_icon()
        links = set(link for conn in icon.connectors.values() for link in conn.links if link.src_connector == conn)
        animation_group = QParallelAnimationGroup(item)
        for link in links:
            animation_group.addAnimation(link.make_execution_animation())
        return animation_group
Пример #5
0
class BubbleLabel(QWidget):

    BackgroundColor = QColor(195, 195, 195)
    BorderColor = QColor(150, 150, 150)

    def __init__(self, *args, **kwargs):
        text = kwargs.pop("text", "")
        super(BubbleLabel, self).__init__(*args, **kwargs)
        # 设置无边框置顶
        self.setWindowFlags(
            Qt.Window | Qt.Tool | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.X11BypassWindowManagerHint)
        # 设置最小宽度和高度
        self.setMinimumWidth(200)
        self.setMinimumHeight(48)
        self.setAttribute(Qt.WA_TranslucentBackground, True)
        layout = QVBoxLayout(self)
        # 左上右下的边距(下方16是因为包括了三角形)
        layout.setContentsMargins(8, 8, 8, 16)
        self.label = QLabel(self)
        layout.addWidget(self.label)
        self.setText(text)
        # 获取屏幕高宽
        self._desktop = QApplication.instance().desktop()

    def setText(self, text):
        self.label.setText(text)

    def text(self):
        return self.label.text()

    def stop(self):
        self.hide()
        self.animationGroup.stop()
        self.close()

    def show(self):
        super(BubbleLabel, self).show()
        # 窗口开始位置
        startPos = QPoint(
            self._desktop.screenGeometry().width() - self.width() - 100,
            self._desktop.availableGeometry().height() - self.height())
        endPos = QPoint(
            self._desktop.screenGeometry().width() - self.width() - 100,
            self._desktop.availableGeometry().height() - self.height() * 3 - 5)
        print(startPos, endPos)
        self.move(startPos)
        # 初始化动画
        self.initAnimation(startPos, endPos)

    def initAnimation(self, startPos, endPos):
        # 透明度动画
        opacityAnimation = QPropertyAnimation(self, b"opacity")
        opacityAnimation.setStartValue(1.0)
        opacityAnimation.setEndValue(0.0)
        # 设置动画曲线
        opacityAnimation.setEasingCurve(QEasingCurve.InQuad)
        opacityAnimation.setDuration(4000)  # 在4秒的时间内完成
        # 往上移动动画
        moveAnimation = QPropertyAnimation(self, b"pos")
        moveAnimation.setStartValue(startPos)
        moveAnimation.setEndValue(endPos)
        moveAnimation.setEasingCurve(QEasingCurve.InQuad)
        moveAnimation.setDuration(5000)  # 在5秒的时间内完成
        # 并行动画组(目的是让上面的两个动画同时进行)
        self.animationGroup = QParallelAnimationGroup(self)
        self.animationGroup.addAnimation(opacityAnimation)
        self.animationGroup.addAnimation(moveAnimation)
        self.animationGroup.finished.connect(self.close)  # 动画结束时关闭窗口
        self.animationGroup.start()

    def paintEvent(self, event):
        super(BubbleLabel, self).paintEvent(event)
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)  # 抗锯齿

        rectPath = QPainterPath()  # 圆角矩形
        triPath = QPainterPath()  # 底部三角形

        height = self.height() - 8  # 往上偏移8
        rectPath.addRoundedRect(QRectF(0, 0, self.width(), height), 5, 5)
        x = self.width() / 5 * 4
        triPath.moveTo(x, height)  # 移动到底部横线4/5处
        # 画三角形
        triPath.lineTo(x + 6, height + 8)
        triPath.lineTo(x + 12, height)

        rectPath.addPath(triPath)  # 添加三角形到之前的矩形上

        # 边框画笔
        painter.setPen(QPen(self.BorderColor, 1, Qt.SolidLine,
                            Qt.RoundCap, Qt.RoundJoin))
        # 背景画刷
        painter.setBrush(self.BackgroundColor)
        # 绘制形状
        painter.drawPath(rectPath)
        # 三角形底边绘制一条线保证颜色与背景一样
        painter.setPen(QPen(self.BackgroundColor, 1,
                            Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
        painter.drawLine(x, height, x + 12, height)

    def windowOpacity(self):
        return super(BubbleLabel, self).windowOpacity()

    def setWindowOpacity(self, opacity):
        super(BubbleLabel, self).setWindowOpacity(opacity)

    # 由于opacity属性不在QWidget中需要重新定义一个
    opacity = pyqtProperty(float, windowOpacity, setWindowOpacity)
Пример #6
0
    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
Пример #7
0
 def run_execution_leave_animation(self, skipped):
     animation_group = QParallelAnimationGroup(self._toolbox)
     for link in self.outgoing_links():
         animation_group.addAnimation(
             link.make_execution_animation(skipped))
     animation_group.start()
Пример #8
0
    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
Пример #9
0
class Spoiler(QWidget):
    class Orientation(Enum):
        HORIZONTAL = 1
        VERTICAL = 2

    def __init__(self,
                 orientation=Orientation.HORIZONTAL,
                 animationDuration=250,
                 parent=None):
        QWidget.__init__(self, parent)

        self.opened = False
        self.orientation = orientation
        self.animationDuration = animationDuration
        self.mainLayout = None
        self.animator = QParallelAnimationGroup()

        if orientation is self.Orientation.HORIZONTAL:
            self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)

            self.setMaximumWidth(0)
            self.setMinimumWidth(0)
            # let the entire widget grow and shrink with its content
            self.animator.addAnimation(QPropertyAnimation(self))
            self.animator.addAnimation(
                QPropertyAnimation(self, b"minimumWidth"))
            self.animator.addAnimation(
                QPropertyAnimation(self, b"maximumWidth"))

        elif orientation is self.Orientation.VERTICAL:
            self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)

            self.setMaximumHeight(0)
            self.setMinimumHeight(0)
            # let the entire widget grow and shrink with its content
            self.animator.addAnimation(QPropertyAnimation(self))
            self.animator.addAnimation(
                QPropertyAnimation(self, b"minimumHeight"))
            self.animator.addAnimation(
                QPropertyAnimation(self, b"maximumHeight"))

    def open(self):
        self.animator.setDirection(QAbstractAnimation.Forward)
        self.animator.start()
        self.opened = True

    def close(self):
        self.animator.setDirection(QAbstractAnimation.Backward)
        self.animator.start()
        self.opened = False

    def isOpened(self):
        return self.opened

    def setContentLayout(self, contentLayout):
        self.setLayout(contentLayout)

        if self.orientation is self.Orientation.HORIZONTAL:
            collapsedSize = self.maximumWidth()
            contentSize = contentLayout.sizeHint().width()
        elif self.orientation is self.Orientation.VERTICAL:
            collapsedSize = self.maximumHeight()
            contentSize = contentLayout.sizeHint().height()

        i = 0
        while i < self.animator.animationCount():
            animation = self.animator.animationAt(i)
            animation.setDuration(self.animationDuration)
            animation.setStartValue(collapsedSize)
            animation.setEndValue(collapsedSize + contentSize)
            i += 1
    def transicion_stacked(self, index_final, indexSiguientes=[]):
        """ Animacion de cambio del StackedWidget """
        '''
        # PARAMETROS
        *index_final: 
            Index de pagina al que se dirije.

        *index_siguientes: 
            Los index que siguen despues de el indicado
            del "0" le sigue [1,2], de "1" sigue [2] 
            pero del "2" no le sigue nadie []
            (esto para tener un efecto avance y retroceso)
        '''

        # obtener index actual /*/*/*/*/*/*/
        index_inicio = self.miStack.currentIndex()

        # condicionamiento /*/*/*/*/*/*/
        '1: no debe haber transciciones en ejecucion'
        '2: el inicio y final no puede ser el mismo (index)'
        if (self.ctrl_animacion) or (index_final == index_inicio):
            return

        # control de transicion (activo) /*/*/*/*/*/*/
        self.ctrl_animacion = True

        # index /*/*/*/*/*/*/
        self.index_inicio = index_inicio
        self.index_final = index_final
        '''
        #-TANSICIONES-*-*-*-*-*-*-*-*-*-*-*

        ↓ offsetx = 0; offsety = alto_stk
        ↑ offsetx = 0; offsety = -alto_stk
        ← offsetx = ancho_stk; offsety = 0
        → offsetx = -ancho_stk; offsety = 0

        #-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
        '''

        # tamaño de widget para transciciones /*/*/*/*/*/*/
        ancho_stk = self.miStack.width()
        alto_stk = self.miStack.height()

        # efecto de avance y retroceso /*/*/*/*/*/*/
        if (self.index_inicio in indexSiguientes):
            offsetx = -ancho_stk
            offsety = 0
        else:
            offsetx = ancho_stk
            offsety = 0

        # configuraciones /*/*/*/*/*/*/
        velocidad_tansicion = 600
        efecto_transicion = QEasingCurve.OutCubic  # OutCubic | InOutQuint | OutExpo
        self.miStack.widget(self.index_final).resize(
            ancho_stk, alto_stk)  # establecer tamaño

        # posicionamiento del widget /*/*/*/*/*/*/
        self.punto_actual = self.miStack.widget(self.index_inicio).pos()
        self.punto_final = self.miStack.widget(self.index_final).pos()

        # mostrar el siguiente widged en la transicion /*/*/*/*/*/*/
        self.miStack.widget(self.index_final).show()

        # obtener punto de referencia /*/*/*/*/*/*/
        offset = QPoint(offsetx, offsety)

        # animacion de transcicion de widgets /*/*/*/*/*/*/
        animacion_stack = QParallelAnimationGroup(
            self.miStack, finished=self.realizarAnimacion)

        animacion_inicio = QPropertyAnimation(
            self.miStack.widget(self.index_inicio),
            b"pos",
            duration=velocidad_tansicion,
            easingCurve=efecto_transicion,
            startValue=self.punto_actual,
            endValue=self.punto_final - offset)

        animacion_final = QPropertyAnimation(
            self.miStack.widget(self.index_final),
            b"pos",
            duration=velocidad_tansicion,
            easingCurve=efecto_transicion,
            startValue=self.punto_actual + offset,
            endValue=self.punto_final)

        animacion_stack.addAnimation(animacion_inicio)
        animacion_stack.addAnimation(animacion_final)

        # iniciar efecto /*/*/*/*/*/*/
        animacion_stack.start(QAbstractAnimation.DeleteWhenStopped)
Пример #11
0
class QtBubbleLabel(QWidget):
    BackgroundColor = QColor(195, 195, 195)
    BorderColor = QColor(150, 150, 150)

    def __init__(self, *args, **kwargs):
        super(QtBubbleLabel, self).__init__(*args, **kwargs)
        self.setWindowFlags(Qt.Window | Qt.Tool | Qt.FramelessWindowHint
                            | Qt.WindowStaysOnTopHint
                            | Qt.X11BypassWindowManagerHint)
        self.setMinimumWidth(200)
        self.setMinimumHeight(48)
        self.setAttribute(Qt.WA_TranslucentBackground, True)
        layout = QVBoxLayout(self)
        layout.setContentsMargins(8, 8, 8, 16)
        self.label = QLabel(self)
        layout.addWidget(self.label)
        self._desktop = QApplication.instance().desktop()
        self.animationGroup = QParallelAnimationGroup(self)

    def setText(self, text):
        self.label.setText(text)

    def text(self):
        return self.label.text()

    def stop(self):
        self.hide()
        self.animationGroup.stop()
        self.animationGroup.clear()
        self.close()

    def show(self):
        super(QtBubbleLabel, self).show()
        x = self.parent().geometry().x()
        y = self.parent().geometry().y()
        x2 = self.parent().size().width()
        y2 = self.parent().size().height()
        startPos = QPoint(x + int(x2 / 2) - int(self.width() / 2),
                          y + int(y2 / 2))
        endPos = QPoint(x + int(x2 / 2) - int(self.width() / 2),
                        y + int(y2 / 2) - self.height() * 3 - 5)
        self.move(startPos)
        # 初始化动画
        self.initAnimation(startPos, endPos)

    def initAnimation(self, startPos, endPos):
        # 透明度动画
        opacityAnimation = QPropertyAnimation(self, b"opacity")
        opacityAnimation.setStartValue(1.0)
        opacityAnimation.setEndValue(0.0)
        # 设置动画曲线
        opacityAnimation.setEasingCurve(QEasingCurve.InQuad)
        opacityAnimation.setDuration(3000)  # 在4秒的时间内完成
        # 往上移动动画
        moveAnimation = QPropertyAnimation(self, b"pos")
        moveAnimation.setStartValue(startPos)
        moveAnimation.setEndValue(endPos)
        moveAnimation.setEasingCurve(QEasingCurve.InQuad)
        moveAnimation.setDuration(4000)  # 在5秒的时间内完成
        # 并行动画组(目的是让上面的两个动画同时进行)
        self.animationGroup.addAnimation(opacityAnimation)
        self.animationGroup.addAnimation(moveAnimation)
        self.animationGroup.finished.connect(self.close)  # 动画结束时关闭窗口
        self.animationGroup.start()

    def paintEvent(self, event):
        super(QtBubbleLabel, self).paintEvent(event)
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)  # 抗锯齿

        rectPath = QPainterPath()  # 圆角矩形

        height = self.height() - 8  # 往上偏移8
        rectPath.addRoundedRect(QRectF(0, 0, self.width(), height), 5, 5)
        x = self.width() / 5 * 4
        # 边框画笔
        painter.setPen(
            QPen(self.BorderColor, 1, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
        # 背景画刷
        painter.setBrush(self.BackgroundColor)
        # 绘制形状
        painter.drawPath(rectPath)

    def windowOpacity(self):
        return super(QtBubbleLabel, self).windowOpacity()

    def setWindowOpacity(self, opacity):
        super(QtBubbleLabel, self).setWindowOpacity(opacity)

    opacity = Property(float, windowOpacity, setWindowOpacity)

    def ShowMsg(self, text):
        self.stop()
        self.setText(text)
        self.setStyleSheet("color:black")
        self.show()

    @staticmethod
    def ShowMsgEx(owner, text):
        data = QtBubbleLabel(owner)
        data.setText(text)
        data.setStyleSheet("color:black")
        data.show()

    def ShowError(self, text):
        self.stop()
        self.setText(text)
        self.setStyleSheet("color:red")
        self.show()

    @staticmethod
    def ShowErrorEx(owner, text):
        data = QtBubbleLabel(owner)
        data.setText(text)
        data.setStyleSheet("color:red")
        data.show()