Esempio n. 1
0
class MainWindow(QGraphicsView):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.updateTimer = QTimer(self)
        self.demoStartTime = QTime()
        self.fpsTime = QTime()
        self.background = QPixmap()

        self.scene = None
        self.mainSceneRoot = None
        self.frameTimeList = []
        self.fpsHistory = []

        self.currentFps = Colors.fps
        self.fpsMedian = -1
        self.fpsLabel = None
        self.pausedLabel = None
        self.doneAdapt = False
        self.useTimer = False
        self.updateTimer.setSingleShot(True)
        self.companyLogo = None
        self.qtLogo = None

        self.setupWidget()
        self.setupScene()
        self.setupSceneItems()
        self.drawBackgroundToPixmap()

    def setupWidget(self):
        desktop = QApplication.desktop()
        screenRect = desktop.screenGeometry(desktop.primaryScreen())
        windowRect = QRect(0, 0, 800, 600)

        if screenRect.width() < 800:
            windowRect.setWidth(screenRect.width())

        if screenRect.height() < 600:
            windowRect.setHeight(screenRect.height())

        windowRect.moveCenter(screenRect.center())
        self.setGeometry(windowRect)
        self.setMinimumSize(80, 60)

        self.setWindowTitle("PyQt Examples")
        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setFrameStyle(QFrame.NoFrame)
        self.setRenderingSystem()
        self.updateTimer.timeout.connect(self.tick)

    def setRenderingSystem(self):
        self.setCacheMode(QGraphicsView.CacheBackground)
        self.setViewport(QWidget())

    def start(self):
        self.switchTimerOnOff(True)
        self.demoStartTime.restart()
        MenuManager.instance().itemSelected(MenuManager.ROOT,
                Colors.rootMenuName)
        Colors.debug("- starting demo")

    def enableMask(self, enable):
        if not enable or Colors.noWindowMask:
            self.clearMask()
        else:
            region = QPolygon([
                    # North side.
                    0, 0,
                    800, 0,
                    # East side.
                    # 800, 70,
                    # 790, 90,
                    # 790, 480,
                    # 800, 500,
                    800, 600,
                    # South side.
                    700, 600,
                    670, 590,
                    130, 590,
                    100, 600,
                    0, 600,
                    # West side.
                    # 0, 550,
                    # 10, 530,
                    # 10, 520,
                    # 0, 520,
                    0, 0])

            self.setMask(QRegion(region))

    def setupScene(self):
        self.scene = QGraphicsScene(self)
        self.scene.setSceneRect(0, 0, 800, 600)
        self.setScene(self.scene)
        self.scene.setItemIndexMethod(QGraphicsScene.NoIndex)

    def switchTimerOnOff(self, on):
        ticker = MenuManager.instance().ticker
        if ticker and ticker.scene():
            ticker.tickOnPaint = not on or Colors.noTimerUpdate

        if on and not Colors.noTimerUpdate:
            self.useTimer = True
            self.fpsTime = QTime.currentTime()
            self.updateTimer.start(int(1000 / Colors.fps))
            update_mode = QGraphicsView.NoViewportUpdate
        else:
            self.useTimer = False
            self.updateTimer.stop()

            if Colors.noTicker:
                update_mode = QGraphicsView.MinimalViewportUpdate
            else:
                update_mode = QGraphicsView.SmartViewportUpdate

        self.setViewportUpdateMode(update_mode)

    def measureFps(self):
        # Calculate time difference.
        t = self.fpsTime.msecsTo(QTime.currentTime())
        if t == 0:
            t = 0.01

        self.currentFps = (1000.0 / t)
        self.fpsHistory.append(self.currentFps)
        self.fpsTime = QTime.currentTime()

        # Calculate median.
        size = len(self.fpsHistory)

        if size == 10:
            self.fpsHistory.sort()
            self.fpsMedian = self.fpsHistory[int(size / 2)]
            if self.fpsMedian == 0:
                self.fpsMedian = 0.01

            self.fpsHistory = []

            return True

        return False

    def forceFpsMedianCalculation(self):
        # Used for adaption in case things are so slow that no median has yet
        # been calculated.
        if self.fpsMedian != -1:
            return

        size = len(self.fpsHistory)

        if size == 0:
            self.fpsMedian = 0.01
            return

        self.fpsHistory.sort()
        self.fpsMedian = self.fpsHistory[size // 2]
        if self.fpsMedian == 0:
            self.fpsMedian = 0.01

    def tick(self):
        medianChanged = self.measureFps()
        self.checkAdapt()

        if medianChanged and self.fpsLabel and Colors.showFps:
            self.fpsLabel.setText("FPS: %d" % int(self.currentFps))

        if MenuManager.instance().ticker:
            MenuManager.instance().ticker.tick()

        self.viewport().update()

        if self.useTimer:
            self.updateTimer.start(int(1000 / Colors.fps))

    def setupSceneItems(self):
        if Colors.showFps:
            self.fpsLabel = DemoTextItem("FPS: --", Colors.buttonFont(),
                    Qt.white, -1, None, DemoTextItem.DYNAMIC_TEXT)
            self.fpsLabel.setZValue(1000)
            self.fpsLabel.setPos(Colors.stageStartX,
                    600 - QFontMetricsF(Colors.buttonFont()).height() - 5)

        self.mainSceneRoot = QGraphicsWidget()
        self.scene.addItem(self.mainSceneRoot)

        self.companyLogo = ImageItem(QImage(':/images/trolltech-logo.png'),
                1000, 1000, None, True, 0.5)
        self.qtLogo = ImageItem(QImage(':/images/qtlogo_small.png'), 1000,
                1000, None, True, 0.5)
        self.companyLogo.setZValue(100)
        self.qtLogo.setZValue(100)
        self.pausedLabel = DemoTextItem("PAUSED", Colors.buttonFont(),
                Qt.white, -1, None)
        self.pausedLabel.setZValue(100)
        fm = QFontMetricsF(Colors.buttonFont())
        self.pausedLabel.setPos(Colors.stageWidth - fm.width("PAUSED"),
                590 - fm.height())
        self.pausedLabel.setRecursiveVisible(False)

    def checkAdapt(self):
        if self.doneAdapt or Colors.noTimerUpdate or self.demoStartTime.elapsed() < 2000:
            return

        self.doneAdapt = True
        self.forceFpsMedianCalculation()
        Colors.benchmarkFps = self.fpsMedian
        Colors.debug("- benchmark: %d FPS" % int(Colors.benchmarkFps))

        if Colors.noAdapt:
            return

        if self.fpsMedian < 30:
            ticker = MenuManager.instance().ticker
            if ticker and ticker.scene():
                self.scene.removeItem(ticker)
                Colors.noTimerUpdate = True
                self.switchTimerOnOff(False)

                if self.fpsLabel:
                    self.fpsLabel.setText("FPS: (%d)" % int(self.fpsMedian))

                Colors.debug("- benchmark adaption: removed ticker (fps < 30)")

            if self.fpsMedian < 20:
                Colors.noAnimations = True
                Colors.debug("- benchmark adaption: animations switched off (fps < 20)")

            Colors.adapted = True

    def drawBackgroundToPixmap(self):
        r = self.scene.sceneRect()
        self.background = QPixmap(qRound(r.width()), qRound(r.height()))
        self.background.fill(Qt.black)
        painter = QPainter(self.background)

        bg = QImage(':/images/demobg.png')
        painter.drawImage(0, 0, bg)

    def drawBackground(self, painter, rect):
        painter.drawPixmap(QPoint(0, 0), self.background)

    def toggleFullscreen(self):
        if self.isFullScreen():
            self.enableMask(True)
            self.showNormal()
            if MenuManager.instance().ticker:
                MenuManager.instance().ticker.pause(False)
        else:
            self.enableMask(False)
            self.showFullScreen()

    def keyPressEvent(self, event):
        if event.key() == Qt.Key_Escape:
            QApplication.quit()
        elif event.key() == Qt.Key_F1:
            s = ""
            s += "\nAdapt: "
            s += ["on", "off"][Colors.noAdapt]
            s += "\nAdaption occured: "
            s += ["no", "yes"][Colors.adapted]
            w = QWidget()
            s += "\nColor bit depth: %d" % w.depth()
            s += "\nWanted FPS: %d" % Colors.fps
            s += "\nBenchmarked FPS: ";
            if Colors.benchmarkFps != -1:
                s += "%d" % Colors.benchmarkFps
            else:
                s += "not calculated"
            s += "\nAnimations: ";
            s += ["on", "off"][Colors.noAnimations]
            s += "\nBlending: ";
            s += ["on", "off"][Colors.useEightBitPalette]
            s += "\nTicker: ";
            s += ["on", "off"][Colors.noTicker]
            s += "\nPixmaps: ";
            s += ["off", "on"][Colors.usePixmaps]
            s += "\nRescale images on resize: ";
            s += ["on", "off"][Colors.noRescale]
            s += "\nTimer based updates: ";
            s += ["on", "off"][Colors.noTimerUpdate]
            s += "\nSeparate loop: ";
            s += ["no", "yes"][Colors.useLoop]
            s += "\nScreen sync: ";
            s += ["yes", "no"][Colors.noScreenSync]
            QMessageBox.information(None, "Current configuration", s)

        super(MainWindow, self).keyPressEvent(event)

    def focusInEvent(self, event):
        if not Colors.pause:
            return

        if MenuManager.instance().ticker:
            MenuManager.instance().ticker.pause(False)

        code = MenuManager.instance().currentMenuCode
        if code in (MenuManager.ROOT, MenuManager.MENU1):
            self.switchTimerOnOff(True)

        self.pausedLabel.setRecursiveVisible(False)

    def focusOutEvent(self, event):
        if not Colors.pause:
            return

        if MenuManager.instance().ticker:
            MenuManager.instance().ticker.pause(True)

        code = MenuManager.instance().currentMenuCode
        if code in (MenuManager.ROOT, MenuManager.MENU1):
            self.switchTimerOnOff(False)

        self.pausedLabel.setRecursiveVisible(True)

    def resizeEvent(self, event):
        self.resetTransform()
        self.scale(event.size().width() / 800.0, event.size().height() / 600.0)

        super(MainWindow, self).resizeEvent(event)

        DemoItem.setTransform(self.transform())

        if self.companyLogo:
            r = self.scene.sceneRect()
            ttb = self.companyLogo.boundingRect()
            self.companyLogo.setPos(int((r.width() - ttb.width()) / 2),
                    595 - ttb.height())
            qtb = self.qtLogo.boundingRect()
            self.qtLogo.setPos(802 - qtb.width(), 0)

        # Changing size will almost always hurt FPS during the change so ignore
        # it.
        self.fpsHistory = []
Esempio n. 2
0
class ItemCircleAnimation(DemoItem):
    def __init__(self, parent=None):
        super(ItemCircleAnimation, self).__init__(parent)

        self.letterList = []
        self.letterCount = Colors.tickerLetterCount
        self.scale = 1.0
        self.showCount = -1
        self.tickOnPaint = False
        self.paused = False
        self.doIntroTransitions = True
        self.setAcceptHoverEvents(True)
        self.setCursor(Qt.OpenHandCursor)
        self.setupGuides()
        self.setupLetters()
        self.useGuideQt()
        self.effect = None

        self.mouseMoveLastPosition = QPointF()
        self.tickTimer = QTime()

    def createLetter(self, c):
        letter = LetterItem(c, self)
        self.letterList.append(letter)

    def setupLetters(self):
        self.letterList = []

        s = Colors.tickerText
        tlen = len(s)
        room = self.letterCount
        while room >= tlen:
            for c in s:
                self.createLetter(c)

            room -= tlen

        # Fill in with blanks.
        while room > 0:
            self.createLetter(' ')
            room -= 1

    def setupGuides(self):
        x = 0
        y = 20

        self.qtGuide1 = GuideCircle(QRectF(x, y, 260, 260), -36, 342)
        GuideLine(QPointF(x + 240, y + 268), self.qtGuide1)
        GuideLine(QPointF(x + 265, y + 246), self.qtGuide1)
        GuideLine(QPointF(x + 158, y + 134), self.qtGuide1)
        GuideLine(QPointF(x + 184, y + 109), self.qtGuide1)
        GuideLine(QPointF(x + 160, y +  82), self.qtGuide1)
        GuideLine(QPointF(x +  77, y + 163), self.qtGuide1)
        GuideLine(QPointF(x + 100, y + 190), self.qtGuide1)
        GuideLine(QPointF(x + 132, y + 159), self.qtGuide1)
        GuideLine(QPointF(x + 188, y + 211), self.qtGuide1)
        GuideCircle(QRectF(x + 30, y + 30, 200, 200), -30, 336, GuideCircle.CW, self.qtGuide1)
        GuideLine(QPointF(x + 238, y + 201), self.qtGuide1)

        y = 30
        self.qtGuide2 = GuideCircle(QRectF(x + 30, y + 30, 200, 200), 135, 270, GuideCircle.CCW)
        GuideLine(QPointF(x + 222, y + 38), self.qtGuide2)
        GuideCircle(QRectF(x, y, 260, 260), 135, 270, GuideCircle.CW, self.qtGuide2)
        GuideLine(QPointF(x + 59, y + 59), self.qtGuide2)

        x = 115
        y = 10
        self.qtGuide3 = GuideLine(QLineF(x, y, x + 30, y))
        GuideLine(QPointF(x + 30, y + 170), self.qtGuide3)
        GuideLine(QPointF(x, y + 170), self.qtGuide3)
        GuideLine(QPointF(x, y), self.qtGuide3)

        self.qtGuide1.setFence(QRectF(0, 0, 800, 600))
        self.qtGuide2.setFence(QRectF(0, 0, 800, 600))
        self.qtGuide3.setFence(QRectF(0, 0, 800, 600))

    def useGuide(self, guide, firstLetter, lastLetter):
        padding = guide.lengthAll() / float(lastLetter - firstLetter)

        for i, letter in enumerate(self.letterList[firstLetter:lastLetter]):
            letter.useGuide(guide, i * padding)

    def useGuideQt(self):
        if self.currGuide is not self.qtGuide1:
            self.useGuide(self.qtGuide1, 0, self.letterCount)
            self.currGuide = self.qtGuide1

    def useGuideTt(self):
        if self.currGuide is not self.qtGuide2:
            split = int(self.letterCount * 5.0 / 7.0)
            self.useGuide(self.qtGuide2, 0, split)
            self.useGuide(self.qtGuide3, split, self.letterCount)
            self.currGuide = self.qtGuide2

    def boundingRect(self):
        return QRectF(0, 0, 300, 320)

    def prepare(self):
        pass

    def switchToNextEffect(self):
        self.showCount += 1

        if self.showCount == 1:
            self.effect = EffectSnake(self.letterList)
        elif self.showCount == 2:
            self.effect = EffectLine(self.letterList)
            self.effect.setPostEffect(PostRotateXYTwist(0.01, 0.0, 0.003, 0.0))
        elif self.showCount == 3:
            self.effect = EffectRaindrops(self.letterList)
            self.effect.setPostEffect(PostRotateXYTwist(0.01, 0.005, 0.003, 0.003))
        elif self.showCount == 4:
            self.effect = EffectScan(self.letterList)
            self.effect.normalMoveSpeed = 0
            self.effect.setPostEffect(PostRotateXY(0.008, 0.0, 0.005, 0.0))
        else:
            self.showCount = 0
            self.effect = EffectWhirlWind(self.letterList)

    def animationStarted(self, id):
        if id == DemoItemAnimation.ANIM_IN:
            if self.doIntroTransitions:
                # Make all letters disappear.
                for letter in self.letterList:
                    letter.setPos(1000, 0)

                self.switchToNextEffect()
                self.useGuideQt()
                self.scale = 1.0

                # The first time we run, we have a rather large delay to
                # perform benchmark before the ticker shows.  But now, since we
                # are showing, use a more appropriate value.
                self.currentAnimation.setStartDelay(1500)
        elif self.effect is not None:
            self.effect.useSheepDog = False

        self.tickTimer = QTime.currentTime()

    def swapModel(self):
        if self.currGuide is self.qtGuide2:
            self.useGuideQt()
        else:
            self.useGuideTt()

    def hoverEnterEvent(self, event):
        # Skip swap here to enhance ticker dragging.
        pass

    def hoverLeaveEvent(self, event):
        self.swapModel()

    def setTickerScale(self, s):
        self.scale = s
        self.qtGuide1.setScale(self.scale, self.scale)
        self.qtGuide2.setScale(self.scale, self.scale)
        self.qtGuide3.setScale(self.scale, self.scale)

    def mousePressEvent(self, event):
        self.mouseMoveLastPosition = event.scenePos();

        if event.button() == Qt.LeftButton:
            self.setCursor(Qt.ClosedHandCursor)
        else:
            self.switchToNextEffect()

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.setCursor(Qt.OpenHandCursor)

    def mouseMoveEvent(self, event):
        newPosition = event.scenePos()
        self.setPosUsingSheepDog(self.pos() + newPosition - self.mouseMoveLastPosition, QRectF(-260, -280, 1350, 1160))
        self.mouseMoveLastPosition = newPosition

    def wheelEvent(self, event):
        if event.angleDelta().y() > 0:
            self.effect.moveSpeed -= 0.20
        else:
            self.effect.moveSpeed += 0.20

        if self.effect.moveSpeed < 0:
            self.effect.moveSpeed = 0.0

    def pause(self, on):
        self.paused = on
        self.tickTimer = QTime.currentTime()

    def tick(self):
        if self.paused or not self.effect:
            return

        t = self.tickTimer.msecsTo(QTime.currentTime())
        self.tickTimer = QTime.currentTime()
        self.effect.tick(t / 10.0)

    def paint(self, painter, opt, widget):
        if self.tickOnPaint:
            self.tick()
Esempio n. 3
0
class ItemCircleAnimation(DemoItem):
    def __init__(self, parent=None):
        super(ItemCircleAnimation, self).__init__(parent)

        self.letterList = []
        self.letterCount = Colors.tickerLetterCount
        self.scale = 1.0
        self.showCount = -1
        self.tickOnPaint = False
        self.paused = False
        self.doIntroTransitions = True
        self.setAcceptHoverEvents(True)
        self.setCursor(Qt.OpenHandCursor)
        self.setupGuides()
        self.setupLetters()
        self.useGuideQt()
        self.effect = None

        self.mouseMoveLastPosition = QPointF()
        self.tickTimer = QTime()

    def createLetter(self, c):
        letter = LetterItem(c, self)
        self.letterList.append(letter)

    def setupLetters(self):
        self.letterList = []

        s = Colors.tickerText
        tlen = len(s)
        room = self.letterCount
        while room >= tlen:
            for c in s:
                self.createLetter(c)

            room -= tlen

        # Fill in with blanks.
        while room > 0:
            self.createLetter(' ')
            room -= 1

    def setupGuides(self):
        x = 0
        y = 20

        self.qtGuide1 = GuideCircle(QRectF(x, y, 260, 260), -36, 342)
        GuideLine(QPointF(x + 240, y + 268), self.qtGuide1)
        GuideLine(QPointF(x + 265, y + 246), self.qtGuide1)
        GuideLine(QPointF(x + 158, y + 134), self.qtGuide1)
        GuideLine(QPointF(x + 184, y + 109), self.qtGuide1)
        GuideLine(QPointF(x + 160, y + 82), self.qtGuide1)
        GuideLine(QPointF(x + 77, y + 163), self.qtGuide1)
        GuideLine(QPointF(x + 100, y + 190), self.qtGuide1)
        GuideLine(QPointF(x + 132, y + 159), self.qtGuide1)
        GuideLine(QPointF(x + 188, y + 211), self.qtGuide1)
        GuideCircle(QRectF(x + 30, y + 30, 200, 200), -30, 336, GuideCircle.CW,
                    self.qtGuide1)
        GuideLine(QPointF(x + 238, y + 201), self.qtGuide1)

        y = 30
        self.qtGuide2 = GuideCircle(QRectF(x + 30, y + 30, 200, 200), 135, 270,
                                    GuideCircle.CCW)
        GuideLine(QPointF(x + 222, y + 38), self.qtGuide2)
        GuideCircle(QRectF(x, y, 260, 260), 135, 270, GuideCircle.CW,
                    self.qtGuide2)
        GuideLine(QPointF(x + 59, y + 59), self.qtGuide2)

        x = 115
        y = 10
        self.qtGuide3 = GuideLine(QLineF(x, y, x + 30, y))
        GuideLine(QPointF(x + 30, y + 170), self.qtGuide3)
        GuideLine(QPointF(x, y + 170), self.qtGuide3)
        GuideLine(QPointF(x, y), self.qtGuide3)

        self.qtGuide1.setFence(QRectF(0, 0, 800, 600))
        self.qtGuide2.setFence(QRectF(0, 0, 800, 600))
        self.qtGuide3.setFence(QRectF(0, 0, 800, 600))

    def useGuide(self, guide, firstLetter, lastLetter):
        padding = guide.lengthAll() / float(lastLetter - firstLetter)

        for i, letter in enumerate(self.letterList[firstLetter:lastLetter]):
            letter.useGuide(guide, i * padding)

    def useGuideQt(self):
        if self.currGuide is not self.qtGuide1:
            self.useGuide(self.qtGuide1, 0, self.letterCount)
            self.currGuide = self.qtGuide1

    def useGuideTt(self):
        if self.currGuide is not self.qtGuide2:
            split = int(self.letterCount * 5.0 / 7.0)
            self.useGuide(self.qtGuide2, 0, split)
            self.useGuide(self.qtGuide3, split, self.letterCount)
            self.currGuide = self.qtGuide2

    def boundingRect(self):
        return QRectF(0, 0, 300, 320)

    def prepare(self):
        pass

    def switchToNextEffect(self):
        self.showCount += 1

        if self.showCount == 1:
            self.effect = EffectSnake(self.letterList)
        elif self.showCount == 2:
            self.effect = EffectLine(self.letterList)
            self.effect.setPostEffect(PostRotateXYTwist(0.01, 0.0, 0.003, 0.0))
        elif self.showCount == 3:
            self.effect = EffectRaindrops(self.letterList)
            self.effect.setPostEffect(
                PostRotateXYTwist(0.01, 0.005, 0.003, 0.003))
        elif self.showCount == 4:
            self.effect = EffectScan(self.letterList)
            self.effect.normalMoveSpeed = 0
            self.effect.setPostEffect(PostRotateXY(0.008, 0.0, 0.005, 0.0))
        else:
            self.showCount = 0
            self.effect = EffectWhirlWind(self.letterList)

    def animationStarted(self, id):
        if id == DemoItemAnimation.ANIM_IN:
            if self.doIntroTransitions:
                # Make all letters disappear.
                for letter in self.letterList:
                    letter.setPos(1000, 0)

                self.switchToNextEffect()
                self.useGuideQt()
                self.scale = 1.0

                # The first time we run, we have a rather large delay to
                # perform benchmark before the ticker shows.  But now, since we
                # are showing, use a more appropriate value.
                self.currentAnimation.setStartDelay(1500)
        elif self.effect is not None:
            self.effect.useSheepDog = False

        self.tickTimer = QTime.currentTime()

    def swapModel(self):
        if self.currGuide is self.qtGuide2:
            self.useGuideQt()
        else:
            self.useGuideTt()

    def hoverEnterEvent(self, event):
        # Skip swap here to enhance ticker dragging.
        pass

    def hoverLeaveEvent(self, event):
        self.swapModel()

    def setTickerScale(self, s):
        self.scale = s
        self.qtGuide1.setScale(self.scale, self.scale)
        self.qtGuide2.setScale(self.scale, self.scale)
        self.qtGuide3.setScale(self.scale, self.scale)

    def mousePressEvent(self, event):
        self.mouseMoveLastPosition = event.scenePos()

        if event.button() == Qt.LeftButton:
            self.setCursor(Qt.ClosedHandCursor)
        else:
            self.switchToNextEffect()

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.setCursor(Qt.OpenHandCursor)

    def mouseMoveEvent(self, event):
        newPosition = event.scenePos()
        self.setPosUsingSheepDog(
            self.pos() + newPosition - self.mouseMoveLastPosition,
            QRectF(-260, -280, 1350, 1160))
        self.mouseMoveLastPosition = newPosition

    def wheelEvent(self, event):
        if event.angleDelta().y() > 0:
            self.effect.moveSpeed -= 0.20
        else:
            self.effect.moveSpeed += 0.20

        if self.effect.moveSpeed < 0:
            self.effect.moveSpeed = 0.0

    def pause(self, on):
        self.paused = on
        self.tickTimer = QTime.currentTime()

    def tick(self):
        if self.paused or not self.effect:
            return

        t = self.tickTimer.msecsTo(QTime.currentTime())
        self.tickTimer = QTime.currentTime()
        self.effect.tick(t / 10.0)

    def paint(self, painter, opt, widget):
        if self.tickOnPaint:
            self.tick()
Esempio n. 4
0
class timer(QMainWindow):
    def __init__(self):
        super(timer, self).__init__()
        self.initial_variables()  #zd
        self.init_ui()
        self.show()

    def init_ui(self):
        self.time = QTimer(self)
        self.time.setInterval(1000)
        self.time.timeout.connect(self.refresh)
        self.time.timeout.connect(self.skip_day)  #zd

        self.time_start_up = QTime(0, 0, 0)  #正计时的开始时间
        self.time_start_fall = QTime(23, 59, 59)  #倒计时结束时分秒
        self.time_start_data = QDate.currentDate()  #倒计时结束年月日

        self.time_system = QTimer(self)
        self.time_system.setInterval(1000)
        self.time_system.timeout.connect(self.refresh_system)
        self.time_system.start()

        self.hour = 0  #暂停前已经记录的时分秒
        self.minute = 0
        self.second = 0
        self.interval = 0

        self.time.start()

        self.init_window()
        self.init_lcd()
        self.init_Button()
        self.init_bar()
        self.init_label()

    def init_window(self):
        self.resize(900, 600)
        self.setWindowTitle('觅时')
        self.setWindowIcon(QIcon('./images/others/icon.png'))
        self.image_file = "./images/background/timg.png"
        mixer.init()
        self.sound = mixer.music.load(
            "./sound/Berliner Philharmoniker.mp3")  #默认背景音乐
        mixer.music.play(-1, 0.0)

    def init_bar(self):
        self.statusBar()
        menubar = self.menuBar()
        menubar.setNativeMenuBar(False)
        background_menu = menubar.addMenu('背景图片')
        sound_menu = menubar.addMenu('背景音乐')
        model_menu = menubar.addMenu('窗口模式')

        self.open_picture_action = QAction('本地图片', self)
        background_menu.addAction(self.open_picture_action)
        self.open_picture_action.triggered.connect(self.open_picture)

        self.open_music_action = QAction('本地音乐', self)
        self.stop_music_action = QAction('音乐暂停', self)
        self.continue_music_action = QAction('音乐继续', self)
        self.start_music_action = QAction('从头播放', self)
        sound_menu.addAction(self.open_music_action)
        sound_menu.addAction(self.stop_music_action)
        sound_menu.addAction(self.continue_music_action)
        sound_menu.addAction(self.start_music_action)
        self.open_music_action.triggered.connect(self.open_music)
        self.stop_music_action.triggered.connect(self.stop_music)
        self.continue_music_action.triggered.connect(self.continue_music)
        self.start_music_action.triggered.connect(self.start_music)

        self.float_action = QAction('悬浮窗', self)
        self.normal_action = QAction('正常窗口', self)
        model_menu.addAction(self.float_action)
        model_menu.addAction(self.normal_action)
        self.float_action.triggered.connect(self.float)
        self.normal_action.triggered.connect(self.normal)

    def open_picture(self):
        #选择本地图片
        self.image_file, _ = QFileDialog.getOpenFileName(
            self, 'Open file', './images/background',
            'Image files (*.jpg *.gif *.png *.jpeg)')
        self.setAutoFillBackground(True)
        if path.exists(self.image_file) == False:
            return
        palette = QPalette()
        palette.setBrush(
            QPalette.Background,
            QBrush(
                QPixmap(self.image_file).scaled(self.size(),
                                                Qt.IgnoreAspectRatio,
                                                Qt.SmoothTransformation)))
        self.setPalette(palette)

    def open_music(self):
        #选择本地音乐
        self.music_file, _ = QFileDialog.getOpenFileName(
            self, 'Open file', './sound', 'Image files (*.mp3 *.wan *.midi)')
        if path.exists(self.music_file) == False:
            return
        mixer.init()
        self.sound = mixer.music.load(self.music_file)
        mixer.music.play(-1, 0.0)

    def stop_music(self):
        #音乐暂停
        mixer.music.pause()

    def continue_music(self):
        #音乐继续
        mixer.music.unpause()

    def start_music(self):
        #音乐从头开始
        mixer.music.play()

    def init_lcd(self):
        #正计时LCD
        self.lcd1 = QLCDNumber(self)
        self.lcd1.setStyleSheet("background: transparent;font-size:50000px")
        self.lcd1.setObjectName("lcd1")
        self.lcd1.setDigitCount(12)
        self.lcd1.setMode(QLCDNumber.Dec)
        self.lcd1.setSegmentStyle(QLCDNumber.Flat)
        self.lcd1.setVisible(True)

        #倒计时LCD
        self.lcd2 = QLCDNumber(self)
        self.lcd2.setStyleSheet("background: transparent;font-size:50000px")
        self.lcd2.setObjectName("lcd2")
        self.lcd2.setDigitCount(12)
        self.lcd2.setMode(QLCDNumber.Dec)
        self.lcd2.setSegmentStyle(QLCDNumber.Flat)
        self.lcd2.setVisible(False)

        #系统时间LCD
        self.lcd3 = QLCDNumber(self)
        self.lcd3.setStyleSheet(
            "background: transparent;font-size:50000px;color:rgb(255,255,255)")
        self.lcd3.setObjectName("lcd3")
        self.lcd3.setDigitCount(12)
        self.lcd3.setMode(QLCDNumber.Dec)
        self.lcd3.setSegmentStyle(QLCDNumber.Flat)

    def init_label(self):
        #显示标签
        self.label = QLabel("", self)
        self.label.setVisible(True)
        self.label.setFixedWidth(500)
        self.label.setFixedHeight(100)
        self.setStyleSheet(
            "QLabel{font-size:30px;font-weight:normal;font-family:Arial;}")
        self.label.setGeometry(QRect(300, 100, 20, 11))

    def float(self):
        #进入悬浮窗
        self.hide()
        self.resize(550, 60)
        # self.setWindowFlags(QtCore.Qt.WindowMinimizeButtonHint)
        self.lcd3.setVisible(False)
        self.splider.setVisible(False)
        self.label.setVisible(False)
        #self.setWindowFlags(Qt.WindowMaximizeButtonHint)
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)

        self.setAutoFillBackground(True)
        palette = QPalette()
        palette.setBrush(
            QPalette.Background,
            QBrush(
                QPixmap(self.image_file).scaled(self.size(),
                                                Qt.IgnoreAspectRatio,
                                                Qt.SmoothTransformation)))
        self.setPalette(palette)

        self.show()
        self.showNormal()

    def normal(self):
        #退出悬浮窗
        self.hide()
        self.resize(900, 500)
        screen = QDesktopWidget().screenGeometry()
        size = self.geometry()
        self.move((screen.width() - size.width()) / 2,
                  (screen.height() - size.height()) / 3)
        self.setWindowFlags(Qt.Widget)
        self.lcd3.setVisible(True)
        self.splider.setVisible(True)
        self.label.setVisible(True)
        self.show()

    def resizeEvent(self, *args, **kwargs):
        width = self.width()
        height = self.height()
        self.lcd1.setGeometry(
            QRect((width - 300) / 2, (height - 111) / 2, 300, 111))
        self.lcd2.setGeometry(
            QRect((width - 300) / 2, (height - 111) / 2, 300, 111))
        self.lcd3.setGeometry(QRect(width - 200, height - 100, 200, 111))
        self.label.setGeometry(QRect((width - 75) / 2, height / 2, 300, 111))

        self.setAutoFillBackground(True)
        palette = QPalette()
        palette.setBrush(
            QPalette.Background,
            QBrush(
                QPixmap(self.image_file).scaled(self.size(),
                                                Qt.IgnoreAspectRatio,
                                                Qt.SmoothTransformation)))
        self.setPalette(palette)

    def init_Button(self):
        #开始结束按钮
        self.state_start_end = 0
        self.pushButton = QPushButton()
        self.pushButton.setStyleSheet("background:transparent;")
        self.pushButton.setText("")
        icon = QIcon()
        icon.addPixmap(QPixmap(":/start/start.png"))
        self.pushButton.setIcon(icon)
        self.pushButton.setIconSize(QSize(30, 30))
        self.pushButton.setCheckable(True)
        self.pushButton.setFlat(True)
        self.pushButton.setObjectName("开始/结束")
        self.pushButton.clicked.connect(self.start_end)

        #暂停继续按钮
        self.state_continue_stop = 0
        self.pushButton_2 = QPushButton()
        self.pushButton_2.setStyleSheet("background:transparent;")
        self.pushButton_2.setText("")
        icon1 = QIcon()
        icon1.addPixmap(QPixmap(":/on/stop.png"))
        self.pushButton_2.setIcon(icon1)
        self.pushButton_2.setIconSize(QSize(30, 30))
        self.pushButton_2.setCheckable(True)
        self.pushButton_2.setFlat(True)
        self.pushButton_2.setObjectName("pushButton_2")
        self.pushButton_2.clicked.connect(self.continue_stop)

        #数据分析按钮
        self.toolButton = QToolButton()
        self.toolButton.setLayoutDirection(Qt.LeftToRight)
        self.toolButton.setStyleSheet("background:transparent;")
        icon2 = QIcon()
        icon2.addPixmap(QPixmap(":/analytics/analytics.png"), QIcon.Normal,
                        QIcon.Off)
        self.toolButton.setIcon(icon2)
        self.toolButton.setIconSize(QSize(30, 30))
        self.toolButton.setAutoRaise(True)
        self.toolButton.setObjectName("toolButton")
        self.toolButton.clicked.connect(self.analyze)

        #声音播放静音按钮
        self.sound_state = 0
        self.pushButton_4 = QPushButton()
        self.pushButton_4.setStyleSheet("background:transparent;")
        self.pushButton_4.setText("")
        icon3 = QIcon()
        icon3.addPixmap(QPixmap(":/sound/sound.png"), QIcon.Normal, QIcon.Off)
        icon3.addPixmap(QPixmap(":/sound_off/Sound_off.png"), QIcon.Normal,
                        QIcon.On)
        self.pushButton_4.setIcon(icon3)
        self.pushButton_4.setIconSize(QSize(30, 30))
        self.pushButton_4.setCheckable(True)
        self.pushButton_4.setFlat(True)
        self.pushButton_4.setObjectName("pushButton_4")
        self.pushButton_4.clicked.connect(self.sound_renew)
        #self.pushButton_4.rclicked.connect(self.sound_renew())

        #声音大小调节按钮
        self.splider = QSlider(Qt.Horizontal)
        self.splider.valueChanged.connect(self.valChange)
        self.splider.setMinimum(0)
        self.splider.setMaximum(100)
        self.splider.setSingleStep(1)
        self.splider.setTickInterval(1)
        self.splider.setValue(100)

        #布局
        hbox = QHBoxLayout()
        vbox = QVBoxLayout()
        hbox.addWidget(self.pushButton)
        hbox.addWidget(self.pushButton_2)
        hbox.addWidget(self.toolButton)
        hbox.addWidget(self.pushButton_4)
        hbox.addWidget(self.splider)
        hbox.addStretch(1)
        vbox.addStretch(1)
        vbox.addLayout(hbox)
        main_frame = QWidget()
        main_frame.setLayout(vbox)
        self.setCentralWidget(main_frame)

    def refresh(self):
        #正计时
        self.startDate_up = QDateTime(
            QDate.currentDate(),
            self.time_start_up).toMSecsSinceEpoch()  #显示正计时
        self.endDate_up = QDateTime.currentMSecsSinceEpoch()
        interval_up = self.endDate_up - self.startDate_up + self.interval
        if interval_up > 0:
            hour = interval_up // (60 * 60 * 1000)
            min = (interval_up - hour * 60 * 60 * 1000) // (60 * 1000)
            sec = (interval_up - hour * 60 * 60 * 1000 -
                   min * 60 * 1000) // 1000
            intervals = '0' * (2 - len(str(hour))) + str(
                hour) + ':' + '0' * (2 - len(str(min))) + str(
                    min) + ':' + '0' * (2 - len(str(sec))) + str(sec)
            self.lcd1.display(intervals)

        #倒计时
        self.startDate_fall = QDateTime.currentMSecsSinceEpoch()  #显示倒计时
        self.endDate_fall = QDateTime(
            self.time_start_data, self.time_start_fall).toMSecsSinceEpoch()
        interval_fall = self.endDate_fall - self.startDate_fall - self.interval
        if interval_fall > 0:
            hour = interval_fall // (60 * 60 * 1000)
            min = (interval_fall - hour * 60 * 60 * 1000) // (60 * 1000)
            sec = (interval_fall - hour * 60 * 60 * 1000 -
                   min * 60 * 1000) // 1000
            intervals = '0' * (2 - len(str(hour))) + str(
                hour) + ':' + '0' * (2 - len(str(min))) + str(
                    min) + ':' + '0' * (2 - len(str(sec))) + str(sec)
            self.lcd2.display(intervals)
            if hour == 0 and min == 0 and sec == 0:
                mixer.init()
                self.sound = mixer.music.load(
                    "./sound/My Soul,Your Beats!.mp3")
                mixer.music.play(-1, 0.0)

    def refresh_system(self):
        hour = QTime.currentTime().hour()  #显示系统时间
        min = QTime.currentTime().minute()
        sec = QTime.currentTime().second()
        intervals = '0' * (2 - len(str(hour))) + str(
            hour) + ':' + '0' * (2 - len(str(min))) + str(
                min) + ':' + '0' * (2 - len(str(sec))) + str(sec)
        self.lcd3.display(intervals)

    def sound_renew(self):
        #背景音乐状态按钮
        #if self.pushButton_4 == Qt.LeftButton:
        if self.sound_state == 0:
            self.sound_state = 1
            mixer.music.set_volume(0.0)
            self.splider.setValue(0)
            self.splider.setEnabled(False)

        else:
            self.sound_state = 0
            mixer.music.set_volume(1.0)
            self.splider.setValue(100)
            self.splider.setEnabled(True)

    def valChange(self):
        #设置音量为滑动条音量
        mixer.music.set_volume(self.splider.value() / 100)

    def start_end(self):
        time_1 = QTimer(self)
        time_1.setInterval(1)
        time_1.timeout.connect(self.state_refresh)
        time_1.start()

        if self.state_start_end % 2 == 0:
            #任务开始
            self.state_continue_stop = 1
            self.statis = statistic()
            self.interval = 0
            self.time.start()

        if self.state_start_end % 2 == 1:
            #任务结束
            self.check = "无"
            text, ok = QInputDialog.getText(self, '任务备注', '任务备注')
            if ok:
                now_end = QDate.currentDate()
                print(now_end.toString(Qt.DefaultLocaleLongDate))  #结束时的年月日
                time_end = QTime.currentTime()
                print(time_end.toString(Qt.DefaultLocaleLongDate))  #结束时的时分秒
                self.new_check = QLabel(text)
                self.check = self.new_check.text()
                print('任务备注=%s' % self.check)  #title

                self.set_end(time_end.toString(Qt.DefaultLocaleLongDate),
                             self.check)  #zd

                icon = QIcon()
                icon.addPixmap(QPixmap(":/start/start.png"))
                self.pushButton.setIcon(icon)
                icon1 = QIcon()
                icon1.addPixmap(QPixmap(":/on/stop.png"))
                self.pushButton_2.setIcon(icon1)

                if self.statis.time_button == 1:
                    mixer.music.stop()
                    mixer.music.load("./sound/Berliner Philharmoniker.mp3")
                    mixer.music.play(-1, 0.0)

                self.time.stop()
            else:
                #没有确认退出
                self.state_start_end += 1
        self.state_start_end += 1

    def state_refresh(self):
        if self.statis.state == 1:
            self.statis.state = 0
            #print(self.statis.label_return)#标签
            start = QDate.currentDate()
            #print(start.toString(Qt.DefaultLocaleLongDate))#开始的年月日
            time_start = QTime.currentTime()
            print(time_start.toString(Qt.DefaultLocaleLongDate))  #开始的时分秒
            self.set_begin(
                start.toString(Qt.DefaultLocaleLongDate),  #zd
                time_start.toString(Qt.DefaultLocaleLongDate),
                self.statis.label_return)
            icon = QIcon()
            icon.addPixmap(QPixmap(":/over/over.png"))
            self.pushButton.setIcon(icon)
            icon1 = QIcon()
            icon1.addPixmap(QPixmap(":/stop/on.png"))
            self.pushButton_2.setIcon(icon1)
            self.label.setText(self.statis.label_return)

            if self.statis.time_button == 0:
                self.time_start_up = time_start
                self.lcd1.setVisible(True)
                self.lcd2.setVisible(False)
            else:
                hour = int(time_start.hour()) + int(
                    self.statis.hour_time_return)
                minute = int(time_start.minute()) + int(
                    self.statis.minute_time_return)
                second = int(time_start.second()) + int(
                    self.statis.second_time_return)
                msec = int(self.statis.hour_time_return) * 3600 * 1000 + int(
                    self.statis.minute_time_return) * 60 * 1000 + int(
                        self.statis.second_time_return) * 1000
                self.time_start_data = start
                if second >= 60:
                    minute += 1
                if minute >= 60:
                    hour += 1
                if hour >= 24:
                    self.time_start_data = start.addDays(1)
                self.time_start_up = time_start
                self.time_start_fall = time_start.addMSecs(msec)
                self.lcd1.setVisible(False)
                self.lcd2.setVisible(True)

        if self.statis.state == 2:
            self.statis.state = 0
            self.state_start_end += 1

    def continue_stop(self):
        #暂停继续
        self.state_continue_stop += 1
        if self.state_start_end % 2 == 1 and self.state_continue_stop % 2 == 1:
            self.statis.state = 1
            self.state_refresh()
            icon1 = QIcon()
            icon1.addPixmap(QPixmap(":/stop/on.png"))
            self.pushButton_2.setIcon(icon1)
            self.time.start()

        if self.state_start_end % 2 == 1 and self.state_continue_stop % 2 == 0:
            self.check = "无"
            text, ok = QInputDialog.getText(self, '任务备注', '任务备注')
            if ok:
                now_end = QDate.currentDate()
                print(now_end.toString(Qt.DefaultLocaleLongDate))  #结束时的年月日
                time_end = QTime.currentTime()
                print(time_end.toString(Qt.DefaultLocaleLongDate))  #结束时的时分秒
                self.new_check = QLabel(text)
                self.check = self.new_check.text()
                print('任务备注=%s' % self.check)  #title
                self.set_end(time_end.toString(Qt.DefaultLocaleLongDate),
                             self.check)  #zd
                self.set_begin(now_end.toString(Qt.DefaultLocaleLongDate),
                               time_end.toString(Qt.DefaultLocaleLongDate), '')
                icon1 = QIcon()
                icon1.addPixmap(QPixmap(":/on/stop.png"))
                self.pushButton_2.setIcon(icon1)

                self.interval += self.time_start_up.msecsTo(time_end)
                if self.interval < 0:
                    self.interval += 86400 * 1000

                self.time.stop()
            else:
                self.state_continue_stop += 1

    #每次开始会调用
    def set_begin(self, year, begin_time, tags):  # zd
        # 年的格式转化
        self.task_is_on = True

        def year_transform(year):
            new_year = ''
            for i in year:
                if i >= '0' and i <= '9':
                    new_year = new_year + i
                else:
                    new_year = new_year + '/'
            return new_year[:-1]

        self.year = year_transform(year)
        self.begin_time = begin_time
        if tags:
            self.tags = tags

    #结束或者暂停会调用 用于写入数据库
    def set_end(self, end_time, title):  #zd
        self.task_is_on = False

        # 判断是否大于1分钟,是则返回true否则false
        def cmp_1min(time1, time2):
            # print('begin compare')
            #print(time1+' '+time2)
            t1 = time1.split(':')
            t1 = [int(x) for x in t1]
            t2 = time2.split(':')
            t2 = [int(x) for x in t2]
            # print('interval is {}'.format(60*( 60*(t2[0]-t1[0])+(t2[1]-t1[1]) )+(t2[2]-t1[2])))
            return 60 * (60 * (t2[0] - t1[0]) +
                         (t2[1] - t1[1])) + (t2[2] - t1[2]) >= 60

        if not cmp_1min(self.begin_time, end_time):
            print('小于1分钟,不予计入')
            QMessageBox.warning(self, '提示', '小于1分钟,不予计入', QMessageBox.Yes)
            return
        obj = {
            'title': title,
            'phase': (self.year, self.begin_time, end_time),
            'tags': self.tags
        }
        if not obj['title']:
            obj['title'] = '(无)'

        print(obj)
        with open('./data/tasks', 'a') as f:
            f.write(dumps(obj) + '\n')

        with open('./data/date_list', 'r') as f:
            date_list = [x.strip() for x in f.readlines()]
            if self.year in date_list:
                return
        with open('./data/date_list', 'a') as f:
            f.write(self.year + '\n')
        print('加入新日期')

    #调用数据分析窗口
    def analyze(self):
        self.anayze_window_opened = True
        self.anayze_window = analysis()

    def closeEvent(self, QCloseEvent):
        res = QMessageBox.question(self, '消息', '是否关闭这个窗口?',
                                   QMessageBox.Yes | QMessageBox.No,
                                   QMessageBox.No)
        if res == QMessageBox.Yes:
            if self.anayze_window_opened:
                self.anayze_window.close()
            if self.task_is_on:
                self.set_end(
                    QTime.currentTime().toString(Qt.DefaultLocaleLongDate),
                    '(无任务名)')
            QCloseEvent.accept()

        else:
            QCloseEvent.ignore()

    def initial_variables(self):  #zd
        self.anayze_window_opened = False
        self.task_is_on = False
        self.year = ''
        self.tt = 0

    def skip_day(self):
        if not self.task_is_on:
            return
        # 年的格式转化
        def year_transform(year):
            new_year = ''
            for i in year:
                if i >= '0' and i <= '9':
                    new_year = new_year + i
                else:
                    new_year = new_year + '/'
            return new_year[:-1]

        #last_time = QTime.currentTime().toString(Qt.DefaultLocaleLongDate)
        last_date = QDate.currentDate().toString(Qt.DefaultLocaleLongDate)
        if self.year != year_transform(last_date):
            print('天数不同!!!')
            self.set_end('23:59:59', '(无)')
            self.set_begin(last_date, '00:00:00', self.tags)

    def test(self):
        self.tt += 1
        print('悬浮窗第{}次'.format(self.tt))