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'resource\Album Cover\ハッピーでバッドな眠りは浅い\ハッピーでバッドな眠りは浅い.png']}  demo = SongInfoCard(songInfo)  demo.setStyleSheet('background:rgb(129,133,137)')  demo.show()  sys.exit(app.exec_())


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM