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();