PyQt5 实现滚动字幕效果且字幕可以更新 可直接简单套用(甚至无需理解)

Pyqt5实现滚动字幕效果

效果演示

话不多说先看效果
在这里插入图片描述

当然,这里我只是简单演示了一下效果,你只需要在我的代码上改动对应的变量,你可以把它按照自己的想法改为新的形式

本文参考了此篇博客:
参考博客

代码讲解

可以直接套用的滚动字幕的class
这里是做的滚动字幕的类,你可以直接把这部分放在你项目里用,具体细节部分可以直接看代码注释
你可以改对应的代码,调整字体、速度、颜色等等
每次更改字幕内容时,只需要调用setText()函数就行了,具体可看我后面的调用方法

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import sys

class ScrollTextWindow(QWidget):
    """ 滚动字幕 """
    def __init__(self, parent=None):
        super().__init__(parent)
        # 设置两段字符串之间留白的宽度
        self.spacing = 100
        # 滚动字幕字体选择
        self.font_style = QFont('Microsoft YaHei', 14, 400)
        self.max_len_text = 400
        # 设置刷新时间和移动距离
        self.timeStep = 20
        self.moveStep = 1
        """ 初始化界面 """
        self.setFixedHeight(115)
        self.setAttribute(Qt.WA_StyledBackground)

        # 下面这部分只是初始化,显示字幕具体内容在setText决定
        # 初始化Text为空
        self.Text = ''
        # 实例化定时器
        self.timer_label = QTimer(self)
        self.TextCurrentIndex = 0
        # 设置字符串溢出标志位
        self.isTextAllOut = False

    def setText(self,Text):
        self.Text = Text
        # 加上下一句是放置更新字幕后之前的timer依旧存在,导致滚动越来越快,不信你可以删了试试
        self.timer_label.deleteLater()
        self.timer_label = QTimer(self)
        self.TextCurrentIndex = 0
        # 设置字符串溢出标志位
        self.isTextAllOut = False
        # 调整窗口宽度
        self.adjustWindowWidth()
        # 初始化定时器
        self.timer_label.setInterval(self.timeStep)
        self.timer_label.timeout.connect(self.updateIndex)
        # 只要有一个字符串宽度大于窗口宽度就开启滚动:
        if self.isTextTooLong:
            self.timer_label.start()

    def move_pose(self,object):
        x,y,w,h = object.x(), object.y(), object.width(), object.height()
        self.move(x+w*0.02, y-h*0.6)  # 移动字幕条的位置,让他处于label框内
        self.max_len_text = w*0.96  # 让字幕显示在框里(略小)

    def getTextWidth(self):
        """ 计算文本的总宽度 """
        songFontMetrics = QFontMetrics(self.font_style)
        self.TextWidth = songFontMetrics.width(self.Text)

    def adjustWindowWidth(self):
        """ 根据字符串长度调整窗口宽度 """
        self.getTextWidth()
        maxWidth = self.TextWidth
        # 判断是否有字符串宽度超过设定的滚动阈值
        self.isTextTooLong = self.TextWidth > self.max_len_text
        # 设置窗口的宽度
        self.setFixedWidth(min(maxWidth, self.max_len_text))

    def updateIndex(self):
        """ 更新下标 """
        self.update()
        self.TextCurrentIndex += 1
        # 设置下标重置条件
        resetTextIndexCond = self.TextCurrentIndex * self.moveStep >= self.TextWidth + self.spacing * self.isTextAllOut
        # 只要条件满足就要重置下标并将字符串溢出置位,保证在字符串溢出后不会因为留出的空白而发生跳变
        if resetTextIndexCond:
            self.TextCurrentIndex = 0
            self.isTextAllOut = True

    def paintEvent(self, e):
        """ 绘制文本 """
        # super().paintEvent(e)
        painter = QPainter(self)
        painter.setPen(Qt.black)
        # 绘制歌名
        painter.setFont(self.font_style)
        if self.isTextTooLong:
            # 实际上绘制了两段完整的字符串
            # 从负的横坐标开始绘制第一段字符串
            painter.drawText(self.spacing * self.isTextAllOut - self.moveStep *
                             self.TextCurrentIndex, 54, self.Text)
            # 绘制第二段字符串
            painter.drawText(self.TextWidth - self.moveStep * self.TextCurrentIndex +
                             self.spacing * (1 + self.isTextAllOut), 54, self.Text)
        else:
            painter.drawText(0, 54, self.Text)

滚动字幕类的调用方法
这里滚动字幕class的输入有一个self.label就是一个Qlabel对象,主要是想实现在滚动字幕外面有一个框,对于滚动字幕的class只有一个辅助定位的作用(详见move_pose()函数)。如果你不想按照这样的方法做,你可以改滚动字幕class里面的move_pose()函数,自己给他一个确定的位置就行了

这里我绑定了一个按钮事件,每次按下按钮就会执行show_another()函数,这个就会改变显示的内容

class Test_window(QtWidgets.QMainWindow, Test_UI.Ui_MainWindow):
    def __init__(self, parent=None):
        super(Test_window, self).__init__(parent)
        self.setupUi(self)
        # 设置边框样式
        self.label.setFrameShape(QtWidgets.QFrame.Box)
        # 设置阴影 据说只有加了这步才能设置边框颜色。///可选样式有Raised、Sunken、Plain(这个无法设置颜色)等
        self.label.setFrameShadow(QtWidgets.QFrame.Raised)
        # 设置边框样式
        self.label.setStyleSheet('border-width: 1px;border-style: solid;border-color: rgb(255, 170, 0);')
        self.label.setText('')
        self.pushButton.clicked.connect(self.show_another)
        text = '字幕短的时候不滚动'
        # self.show_move_new(text)
        self.scrollTextWindow = ScrollTextWindow(self)
        self.scrollTextWindow.move_pose(self.label)
        self.scrollTextWindow.setText(text)

    def show_another(self):
        text = '字幕长的时候就滚动 哈哈哈哈哈哈'
        self.scrollTextWindow.setText(text)

完整代码

想要直接跑我刚才的效果,创建一个python文件,复制如下代码
这里import Test_UI是调用用qtdesigner做的界面生成的代码,直接见后面的Test_UI.py文件
有这两个文件,直接跑test.py就行了
test.py

import Test_UI
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import sys

class ScrollTextWindow(QWidget):
    """ 滚动字幕 """
    def __init__(self, parent=None):
        super().__init__(parent)
        # 设置两段字符串之间留白的宽度
        self.spacing = 100
        # 滚动字幕字体选择
        self.font_style = QFont('Microsoft YaHei', 14, 400)
        self.max_len_text = 400
        # 设置刷新时间和移动距离
        self.timeStep = 20
        self.moveStep = 1
        """ 初始化界面 """
        self.setFixedHeight(115)
        self.setAttribute(Qt.WA_StyledBackground)

        # 下面这部分只是初始化,显示字幕具体内容在setText决定
        # 初始化Text为空
        self.Text = ''
        # 实例化定时器
        self.timer_label = QTimer(self)
        self.TextCurrentIndex = 0
        # 设置字符串溢出标志位
        self.isTextAllOut = False

    def setText(self,Text):
        self.Text = Text
        # 加上下一句是放置更新字幕后之前的timer依旧存在,导致滚动越来越快,不信你可以删了试试
        self.timer_label.deleteLater()
        self.timer_label = QTimer(self)
        self.TextCurrentIndex = 0
        # 设置字符串溢出标志位
        self.isTextAllOut = False
        # 调整窗口宽度
        self.adjustWindowWidth()
        # 初始化定时器
        self.timer_label.setInterval(self.timeStep)
        self.timer_label.timeout.connect(self.updateIndex)
        # 只要有一个字符串宽度大于窗口宽度就开启滚动:
        if self.isTextTooLong:
            self.timer_label.start()

    def move_pose(self,object):
        x,y,w,h = object.x(), object.y(), object.width(), object.height()
        self.move(x+w*0.02, y-h*0.6)  # 移动字幕条的位置,让他处于label框内
        self.max_len_text = w*0.96  # 让字幕显示在框里(略小)

    def getTextWidth(self):
        """ 计算文本的总宽度 """
        songFontMetrics = QFontMetrics(self.font_style)
        self.TextWidth = songFontMetrics.width(self.Text)

    def adjustWindowWidth(self):
        """ 根据字符串长度调整窗口宽度 """
        self.getTextWidth()
        maxWidth = self.TextWidth
        # 判断是否有字符串宽度超过设定的滚动阈值
        self.isTextTooLong = self.TextWidth > self.max_len_text
        # 设置窗口的宽度
        self.setFixedWidth(min(maxWidth, self.max_len_text))

    def updateIndex(self):
        """ 更新下标 """
        self.update()
        self.TextCurrentIndex += 1
        # 设置下标重置条件
        resetTextIndexCond = self.TextCurrentIndex * self.moveStep >= self.TextWidth + self.spacing * self.isTextAllOut
        # 只要条件满足就要重置下标并将字符串溢出置位,保证在字符串溢出后不会因为留出的空白而发生跳变
        if resetTextIndexCond:
            self.TextCurrentIndex = 0
            self.isTextAllOut = True

    def paintEvent(self, e):
        """ 绘制文本 """
        # super().paintEvent(e)
        painter = QPainter(self)
        painter.setPen(Qt.black)
        # 绘制歌名
        painter.setFont(self.font_style)
        if self.isTextTooLong:
            # 实际上绘制了两段完整的字符串
            # 从负的横坐标开始绘制第一段字符串
            painter.drawText(self.spacing * self.isTextAllOut - self.moveStep *
                             self.TextCurrentIndex, 54, self.Text)
            # 绘制第二段字符串
            painter.drawText(self.TextWidth - self.moveStep * self.TextCurrentIndex +
                             self.spacing * (1 + self.isTextAllOut), 54, self.Text)
        else:
            painter.drawText(0, 54, self.Text)


class Test_window(QtWidgets.QMainWindow, Test_UI.Ui_MainWindow):
    def __init__(self, parent=None):
        super(Test_window, self).__init__(parent)
        self.setupUi(self)
        # 设置边框样式
        self.label.setFrameShape(QtWidgets.QFrame.Box)
        # 设置阴影 据说只有加了这步才能设置边框颜色。///可选样式有Raised、Sunken、Plain(这个无法设置颜色)等
        self.label.setFrameShadow(QtWidgets.QFrame.Raised)
        # 设置边框样式
        self.label.setStyleSheet('border-width: 1px;border-style: solid;border-color: rgb(255, 170, 0);')
        self.label.setText('')
        self.pushButton.clicked.connect(self.show_another)
        text = '字幕短的时候不滚动'
        # self.show_move_new(text)
        self.scrollTextWindow = ScrollTextWindow(self)
        self.scrollTextWindow.move_pose(self.label)
        self.scrollTextWindow.setText(text)

    def show_another(self):
        text = '字幕长的时候就滚动 哈哈哈哈哈哈'
        self.scrollTextWindow.setText(text)

    def show_move_new(self,text):
        print(len(text))
        self.label.setText(text)



if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    test_window = Test_window()
    test_window.show()

    sys.exit(app.exec_())

Test_UI.py

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'Test_UI.ui'
#
# Created by: PyQt5 UI code generator 5.15.7
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(230, 230, 311, 41))
        self.label.setAutoFillBackground(False)
        self.label.setTextFormat(QtCore.Qt.AutoText)
        self.label.setScaledContents(False)
        self.label.setWordWrap(False)
        self.label.setOpenExternalLinks(False)
        self.label.setObjectName("label")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(270, 460, 93, 28))
        self.pushButton.setObjectName("pushButton")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 26))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.label.setText(_translate("MainWindow", "新闻测试"))
        self.pushButton.setText(_translate("MainWindow", "切换"))

  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: 在PyQt5实现UI自适应屏幕大小且可缩放,可以通过调整布局和使用相对大小来实现。 首先,我们可以使用Qt的布局管理器来自动调整部件的大小和位置。常用的布局管理器有QHBoxLayout和QVBoxLayout,可以根据需要嵌套使用。通过将部件添加到布局管理器中,然后将布局管理器设置给窗口,窗口将自动根据窗口大小调整部件的大小和位置。 例如,可以使用QVBoxLayout来垂直排列部件,然后使用QHBoxLayout来水平排列部件。通过在布局管理器中添加部件,并将布局管理器设置给窗口,窗口将根据窗口大小调整部件的大小和位置。 其次,可以使用QSizePolicy来设置部件的大小策略。QSizePolicy有很多选项,例如设置部件在水平和垂直方向上的大小是否可伸缩、是否能够自动填充空间等。通过设置适当的大小策略,可以使部件根据窗口大小自动调整大小。 最后,可以实现窗口的缩放功能。可以通过重新实现窗口的resizeEvent()方法来捕捉窗口大小变化的事件,并在事件发生时根据窗口的大小来调整部件的大小。 综上所述,通过适当地使用布局管理器、大小策略和事件处理,可以实现PyQt5中的UI自适应屏幕大小且可缩放的效果。 ### 回答2: 要实现PyQt5的UI自适应屏幕大小且可缩放,可以使用QGridLayout和QHBoxLayout等布局管理器,并且根据窗口大小的变化进行动态调整。 首先,你可以创建一个主窗口,并设置它的布局管理器为QGridLayout。然后,在布局内添加各种控件,比如按钮、文本框等。然后使用setSizePolicy方法来设置控件的尺寸策略,使其在窗口大小变化时能够自动跟随调整。 接下来,可以重写主窗口类的resizeEvent方法,在窗口大小发生变化时进行布局的调整。在该方法中,可以使用QDesktopWidget类来获取屏幕的宽度和高度,并根据当前屏幕的大小动态调整控件的尺寸和位置。 另外,还可以为主窗口添加一个滚动条,以便在窗口过小的情况下,用户可以通过滚动条来查看完整的内容。在布局管理器中添加一个QScrollArea,并将其作为子窗口添加到主窗口中。 此外,你还可以通过添加一个缩放功能来实现UI的缩放。可以使用QGraphicsView来展示界面,并使用QGraphicsView的scale方法来进行缩放。在主窗口中添加一个QGraphicsView,并在resizeEvent中根据窗口大小的变化来调整缩放比例。 通过上述方法,你可以实现PyQt5的UI自适应屏幕大小且可缩放的功能。当窗口大小发生变化时,控件会根据窗口的大小进行自动调整,并且当窗口过小时,可以通过滚动条进行查看。 ### 回答3: 使用PyQt5实现UI自适应屏幕大小并可缩放的方法如下: 1. 设置UI控件的相对大小:在设计UI界面时,使用相对大小来设置控件的尺寸,而不是使用固定的像素值。可以通过设置控件的大小策略(size policy)来实现,如设置为最小尺寸(QSizePolicy.Minimum),即可使控件根据可用空间自动调整大小。 2. 监听窗口大小变化事件:使用`resizeEvent`方法,可以在窗口大小发生变化时触发相应的事件。通过在该方法中重新计算并设置控件的大小,从而实现UI自适应。 ```python def resizeEvent(self, event): # 获取当前窗口大小 window_size = event.size() # 根据窗口大小重新计算并设置控件的大小 # ... # 调用父类的resizeEvent方法 super().resizeEvent(event) ``` 3. 支持缩放功能:可以使用QGraphicsView或QScrollArea等容器控件作为UI界面的根控件,从而实现缩放功能。在该容器控件上加入需要缩放的控件,并使用`setViewportUpdateMode`方法设置为自动更新视口模式,即可允许用户通过手势或鼠标滚轮来进行缩放操作。 ```python # 使用QGraphicsView作为根控件 self.view = QGraphicsView() # 设置自动更新视口模式 self.view.setViewportUpdateMode(QGraphicsView.FullViewportUpdate) # 加入需要缩放的控件 # ... # 设置根控件 self.setLayout(QVBoxLayout()) self.layout().addWidget(self.view) ``` 通过上述方法,可以实现PyQt5的UI自适应屏幕大小且可缩放的效果
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

玛卡巴卡_qin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值