qt滚动字幕 从右到左和从下到上滚动

qt滚动字幕的控件还是很常用的,但是大部分教程都是从右到左的滚动,所以我就封装了一个控件支持从下到上的滚动。原理都是一样的,利用QTIME去控制文字的位置。先上效果图:

在这里插入图片描述

在这里插入图片描述

话不多上,上代码。

#ifndef SOCROLL_H
#define SOCROLL_H

#include <QLabel>
#include <QPainter>
#include <QPaintEvent>
#include <QObject>
#include <QWidget>
#include <QTimer>
#include <QPainter>
#include <QFontMetrics>
#include <QResizeEvent>
#include <QDebug>
namespace  custom{

/*移动方向*/
enum HEAD{
    RTOL, //从右到左
    DTOT  //从下到上
};

class swscroll : public QLabel
{
     Q_OBJECT

public:
    swscroll(QWidget *parent = nullptr);
    ~swscroll();
    /*设置滚动的文本
    *inparam    scrollText  滚动的文本
    *inparam    eHead   滚动的方向
    */
    int setScrollText(QString scrollText, HEAD eHead);

    /*设置滚动的速度
    *inparam    nMs          每次滚动的毫秒数
    *inparam    nPixelSize   每次滚动距离
    * inparam   nDistance    两个滚动文本间距
    */
    int setDelay(int nMs, int nPixelSize, int nDistance);

    /*计算和保存字符串的换行
    *inparam    strSrcText  滚动文本
    *inparam    nWidth      滚动宽度
    * inparam   font        字体信息
    */
    inline QString LineFeed(const QString strSrcText, int nWidth, QFont font);

protected:
    void resizeEvent(QResizeEvent *event);
    void paintEvent(QPaintEvent *event);
    void timeOut();

private:

    QString m_strScrollText;//滚动的文本
    int m_nMs; //定时器的秒数
    int m_nPixelSize; //移动的像素点
    int m_nMoveOffset;//移动的距离
    int m_nMoveSize; //移动的总大小
    int m_nDistance=0; // 循环滚动的间隔
    QTimer* timer;     //时间定时器

    QVector<QString> m_strArray; //保存换行字符串
    int m_nFontSize; //字体大小
    HEAD m_eHead;   //滚动方向

};
}
#endif // SOCROLL_H
#include "custom/swscroll.h"
using namespace custom;

swscroll::swscroll(QWidget *parent)
    : QLabel(parent)
{
    m_nMs = 0;
    m_nPixelSize = 0;
    m_nMoveSize = 0;
    m_nMoveOffset = 0;
    m_nDistance=0;
    timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this, &swscroll::timeOut);
}

swscroll::~swscroll()
{

}
void swscroll::resizeEvent(QResizeEvent *event)
{
    /*窗体大小改变要重新保存换行字符串*/
    m_strArray.clear();
    LineFeed(m_strScrollText, width(), font());
    QLabel::resizeEvent(event);
}

QString swscroll::LineFeed(const QString strSrcText, int nWidth, QFont font)
{
    QString strText = strSrcText;
    QFontMetrics fm(font);
    if (!strText.isEmpty())
    {
        int j=0,i;
        for ( i = 1; i < strText.size() + 1; i++)
        {
            /*width()-fontMetrics().width("a")*3/2  防止一行最后一个没有显示完全*/
            if (fm.width(strText.mid(j,i-j)) > width()-fontMetrics().width("a")*3/2)
            {
                m_strArray.append(strText.mid(j,i-j));
                j=i;
            }
        }
        if(i != j)
            m_strArray.append(strText.mid(j,i-j));
    }
    return strText;
}

void swscroll::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    QFontMetrics fm(font());

    if (m_strScrollText.isEmpty())
    {
        return;
    }

    if(m_eHead == RTOL)
    {
        int nW = fontMetrics().width( m_strScrollText);
        int nH = fm.height();
        if( width() < nW )
        {
            int nX1 = width() - m_nMoveOffset;
            int nX2 = width()+nW+m_nDistance - m_nMoveOffset;
            painter.drawText(nX1, nH, m_strScrollText);
            painter.drawText(nX2,nH, m_strScrollText);
        }
        else
        {
            painter.drawText( 0, nH, m_strScrollText);
        }
    }
    if(m_eHead == DTOT)
    {
        int nI=0,
            nIndex=1,
            nNextIndex=0,
            nFontHeight =fm.height();

        QString strText = m_strScrollText;
        /*字体大小变化时,重新计算换行字符串*/
        if(QFontInfo(font()).pixelSize() != m_nFontSize)
        {
            m_nFontSize = QFontInfo(font()).pixelSize();
            m_strArray.clear();
            LineFeed(strText, width(), font());
        }

        if( m_strArray.count()*nFontHeight > height())
        {
            nNextIndex=m_strArray.count()+1;
            for (nI = 0; nI < m_strArray.count(); nI++)
            {
                int nX1 = fm.width("a")/2 ,
                        nY1 = height() - m_nMoveOffset + nIndex*fm.height(),
                        nX2 = fm.width("a")/2 ,
                        nY2 = height()+m_nDistance - m_nMoveOffset + nNextIndex*fm.height();

                if( nY1 > 0 && nY1 < height()+fm.height())
                    painter.drawText(nX1,nY1 , m_strArray.at(nI));
                if( nY2 > 0 && nY2 < height()+fm.height())
                    painter.drawText(fm.width("a")/2, nY2, m_strArray.at(nI));
                nIndex++;
                nNextIndex++;

            }
        }
        else
        {
            for (nI = 0; nI < m_strArray.count(); nI++)
            {
                int nX1 = fm.width("a")/2 ,
                        nY1 = nIndex*fm.height();
                painter.drawText(nX1,nY1 , m_strArray.at(nI));
                nIndex++;
            }
        }

    }

}
void swscroll::timeOut()
{
    /*从左到右*/
    if(m_eHead == RTOL)
    {
        m_nMoveSize = fontMetrics().width(m_strScrollText);
        m_nMoveOffset = m_nMoveOffset + m_nPixelSize;
        if(m_nMoveOffset > m_nMoveSize + width()+m_nDistance)
        {
            m_nMoveOffset =width() ;
        }
    }
    /*从下到上*/
    else if(m_eHead == DTOT )
    {
        m_nMoveSize = height()+fontMetrics().height()* (m_strArray.count())+m_nDistance;
        m_nMoveOffset = m_nMoveOffset + m_nPixelSize;
        if(m_nMoveOffset >= m_nMoveSize )
        {
            if( m_nDistance >= 0 )
            {
                m_nMoveOffset =height();
            }
            else
            {
                m_nMoveOffset = 0;
            }
        }
    }
    update();
}

int swscroll::setDelay(int nMs, int nPixelSize, int nDistance)
{
    if(nMs <= 0)
    {
        return -1;
    }
    if(nPixelSize <= 0)
    {
        return -1;
    }
    if(nDistance < 0)
    {
        return -1;
    }
    m_nMs = nMs;
    m_nPixelSize = nPixelSize;
    m_nDistance = nDistance;
    timer->start( nMs );

    return 0;
}
int swscroll::setScrollText(QString scrollText, HEAD eHead  )
{
    if (scrollText.isEmpty())
    {
        return -1;
    }
    m_nMoveOffset =0;
    m_strScrollText = scrollText;
    m_eHead = eHead;
    return 0;
}
#endif // SOCROLL_H

测试:

	custom::swscroll roll;
    QFont ft;
    ft.setPointSize(50);
    roll.setFont(ft);
    roll.setScrollText("abcdefghijklmnopqrstuvwxyz",custom::RTOL);
    //roll.setScrollText("abcdefghijklmnopqrstuvwxyz",custom::DTOT);
    roll.setGeometry(100,100,100,300);
    roll.setDelay(10,1,200);
	roll.show();
Vivado2023是一款集成开发环境软件,用于设计和验证FPGA(现场可编程门阵列)和可编程逻辑器件。对于使用Vivado2023的用户来说,license是必不可少的。 Vivado2023的license是一种许可证,用于授权用户合法使用该软件。许可证分为多种类型,包括评估许可证、开发许可证和节点许可证等。每种许可证都有不同的使用条件和功能。 评估许可证是免费提供的,让用户可以在一段时间内试用Vivado2023的全部功能。用户可以使用这个许可证来了解软件的性能和特点,对于初学者和小规模项目来说是一个很好的选择。但是,使用评估许可证的用户在使用期限过后需要购买正式的许可证才能继续使用软件。 开发许可证是付费的,可以永久使用Vivado2023的全部功能。这种许可证适用于需要长期使用Vivado2023进行开发的用户,通常是专业的FPGA设计师或工程师。购买开发许可证可以享受Vivado2023的技术支持和更新服务,确保软件始终保持最新的版本和功能。 节点许可证是用于多设备或分布式设计的许可证,可以在多个计算机上安装Vivado2023,并共享使用。节点许可证适用于大规模项目或需要多个处理节点进行设计的用户,可以提高工作效率和资源利用率。 总之,Vivado2023 license是用户在使用Vivado2023时必须考虑的问题。用户可以根据自己的需求选择合适的许可证类型,以便获取最佳的软件使用体验。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值