zoukankan      html  css  js  c++  java
  • pyqt5-滚动条

    原文链接: https://blog.51cto.com/u_15127644/2756688

    滚动字幕的视觉效果

    网上有很多博客介绍了滚动字幕的实现方法,懂得都懂,大部是 Ctrl C + Ctrl V,效果还很差,最后还是得靠自己。主要思路就是通过定时器定时刷新+绘制两段完整的字符串来达到 蒙蔽双眼 滚动的效果,具体效果如下图所示

    滚动字幕

    具体实现方式

    ScrollTextWindow 类

    窗口 ScrollTextWindow 上显示歌名和歌手名。通过 QFontMetrics 来计算歌名和歌手名字符串的宽度,选出最大者,再和窗口最大宽度作比较,以设定窗口宽度并决定是否启用滚动效果。在构造函数里面设置了一个 spacing 属性,用来隔开两段相同的字符串,还设置了两个用于标志位 isSongNameAllOut 和 isSongerNameAllOut 来标记字符串是否已经全部移出过窗口,这两个标志位很重要,没弄好标志位的话之后会出现字符串位置的跳变。前面说过,实现滚动效果就是靠绘制两段相同的字符串,所以这两段字符串的第一个字符的横坐标就很重要,通过设置的标志位isXXXAllOutspacing、定时器的溢出次数 currentIndex 以及字符串的移动步长 moveStep 来决定这两个字符串的的横坐标,具体代码如下:

    复制import sys
    
    from PyQt5.QtCore import Qt, QTimer
    from PyQt5.QtGui import QFont, QFontMetrics, QPainter,QPixmap
    from PyQt5.QtWidgets import QApplication, QLabel, QWidget
    
    
    class ScrollTextWindow(QWidget):
        """ 滚动字幕 """
    
        def __init__(self, songName, songerName, parent=None):
            super().__init__(parent)
            self.songName = songName
            self.songerName = songerName
            # 实例化定时器
            self.timer = QTimer(self)
            # 设置刷新时间和移动距离
            self.timeStep = 20
            self.moveStep = 1
            self.songCurrentIndex = 0
            self.songerCurrentIndex = 0
            # 设置字符串溢出标志位
            self.isSongNameAllOut = False
            self.isSongerNameAllOut = False
            # 设置两段字符串之间留白的宽度
            self.spacing = 25
            # 初始化界面
            self.initWidget()
    
        def initWidget(self):
            """ 初始化界面 """
            self.setFixedHeight(115)
            self.setAttribute(Qt.WA_StyledBackground)
            # 调整窗口宽度
            self.adjustWindowWidth()
            # 初始化定时器
            self.timer.setInterval(self.timeStep)
            self.timer.timeout.connect(self.updateIndex)
            # 只要有一个字符串宽度大于窗口宽度就开启滚动:
            if self.isSongerNameTooLong or self.isSongNameTooLong:
                self.timer.start()
    
        def getTextWidth(self):
            """ 计算文本的总宽度 """
            songFontMetrics = QFontMetrics(QFont('Microsoft YaHei', 14, 400))
            self.songNameWidth = songFontMetrics.width(self.songName)
            songerFontMetrics = QFontMetrics(QFont('Microsoft YaHei', 12, 500))
            self.songerNameWidth = songerFontMetrics.width(self.songerName)
    
        def adjustWindowWidth(self):
            """ 根据字符串长度调整窗口宽度 """
            self.getTextWidth()
            maxWidth = max(self.songNameWidth, self.songerNameWidth)
            # 判断是否有字符串宽度超过窗口的最大宽度
            self.isSongNameTooLong = self.songNameWidth > 250
            self.isSongerNameTooLong = self.songerNameWidth > 250
            # 设置窗口的宽度
            self.setFixedWidth(min(maxWidth, 250))
    
        def updateIndex(self):
            """ 更新下标 """
            self.update()
            self.songCurrentIndex += 1
            self.songerCurrentIndex += 1
            # 设置下标重置条件
            resetSongIndexCond = self.songCurrentIndex * 
                self.moveStep >= self.songNameWidth + self.spacing * self.isSongNameAllOut
            resetSongerIndexCond = self.songerCurrentIndex * 
                self.moveStep >= self.songerNameWidth + self.spacing * self.isSongerNameAllOut
            # 只要条件满足就要重置下标并将字符串溢出置位,保证在字符串溢出后不会因为留出的空白而发生跳变
            if resetSongIndexCond:
                self.songCurrentIndex = 0
                self.isSongNameAllOut = True
            if resetSongerIndexCond:
                self.songerCurrentIndex = 0
                self.isSongerNameAllOut = True
    
        def paintEvent(self, e):
            """ 绘制文本 """
            # super().paintEvent(e)
            painter = QPainter(self)
            painter.setPen(Qt.white)
            # 绘制歌名
            painter.setFont(QFont('Microsoft YaHei', 14))
            if self.isSongNameTooLong:
                # 实际上绘制了两段完整的字符串
                # 从负的横坐标开始绘制第一段字符串
                painter.drawText(self.spacing * self.isSongNameAllOut - self.moveStep *
                                 self.songCurrentIndex, 54, self.songName)
                # 绘制第二段字符串
                painter.drawText(self.songNameWidth - self.moveStep * self.songCurrentIndex +
                                 self.spacing * (1 + self.isSongNameAllOut), 54, self.songName)
            else:
                painter.drawText(0, 54, self.songName)
    
            # 绘制歌手名
            painter.setFont(QFont('Microsoft YaHei', 12, 500))
            if self.isSongerNameTooLong:
                painter.drawText(self.spacing * self.isSongerNameAllOut - self.moveStep *
                                 self.songerCurrentIndex, 82, self.songerName)
                painter.drawText(self.songerNameWidth - self.moveStep * self.songerCurrentIndex +
                                 self.spacing * (1 + self.isSongerNameAllOut), 82, self.songerName)
            else:
                painter.drawText(0, 82, self.songerName)
    

    SongInfoCard 类

    父级窗口 SongInfoCard 用来显示专辑封面和滚动字幕,代码如下:

    复制class SongInfoCard(QWidget):
        """ 播放栏左侧歌曲信息卡 """
    
        def __init__(self, songInfo: dict, parent=None):
            super().__init__(parent)
            # 保存信息
            self.songInfo = songInfo
            self.songName = self.songInfo['songName']
            self.songerName = self.songInfo['songer']
            # 实例化小部件
            self.albumPic = QLabel(self)
            self.scrollTextWindow = ScrollTextWindow(
                self.songName, self.songerName, self)
            # 初始化界面
            self.initWidget()
    
        def initWidget(self):
            """ 初始化小部件 """
            self.setFixedHeight(115)
            self.setFixedWidth(115 + 15 + self.scrollTextWindow.width() + 25)
            self.setAttribute(Qt.WA_StyledBackground)
            self.setWindowFlags(Qt.FramelessWindowHint)
            self.scrollTextWindow.move(130, 0)
            self.albumPic.setPixmap(QPixmap(self.songInfo['album'][-1]).scaled(
                                    115, 115, Qt.KeepAspectRatio, Qt.SmoothTransformation))
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        songInfo = {
            'songName': 'ハッピーでバッドな眠りは浅い', 'songer': '鎖那',
            'album': [r'resourceAlbum Coverハッピーでバッドな眠りは浅いハッピーでバッドな眠りは浅い.png']}
        demo = SongInfoCard(songInfo)
        demo.setStyleSheet('background:rgb(129,133,137)')
        demo.show()
        sys.exit(app.exec_())

  • 相关阅读:
    enum
    爬虫实战2:爬头条网美图--Ajax图片加载处理
    爬虫实战1:使用requests和正则爬取电影信息
    爬虫7:selenium
    爬虫6:pyquery库
    爬虫5:beautifulsoup
    爬虫4:re库
    爬虫3:requests库
    爬虫2:urllib
    爬虫1:概述
  • 原文地址:https://www.cnblogs.com/GavinSimons/p/15064001.html
Copyright © 2011-2022 走看看