Qt实现滚动字幕(跑马灯)

大体思路:

借助于QTimer实现,以下为核心思路:

        字幕显示:字幕(字符串,subtitle,长度为记为length)的长度不是固定的,但是显示字幕的容器(控件)的宽度是一定的,每个字符宽度(所占的像素)是一定的,也就是说每次刷新需要显示的字符个数是一定的,记为n,每刷新一次,就是从原始字幕(subtitle)中不同的位置截取n个字符进行显示;

        字幕滚动:如果每次都从0的位置开始截取字幕的话,那么字符一直就是字幕的前n个字符,是无法看到滚动效果的,我们只需要每刷新一次,将开始截取的位置(index)+ 1,然后再截取随后的n个字符,并进行显示,即可达到字幕滚动的目的;

        字幕循环:字幕现在可以显示和滚动了,但是滚动的时候,会出现一种情况,上一次的尾巴(t个字符)和下一次的头(n-t个字符)同时出现,这种情况该如何解决?小技巧:将字幕乘以2(即subtitle += subtitle),这样我们就可以截取到像上面所描述的那样的一个长度为n的字符串。如果开始截取的位置(index)等于length(index == length),则将截取位置归为0(index = 0),从而达到循环的目的;

        其它:相邻两次字幕之间靠得很紧密,不好看,我们可以现在字幕后面加些空格(即subtitle += "       "),然后再给他乘以2,这样相邻两次之间就会存在间隔,看起来比较舒服。

完成代码如下:

#include "TextTicker.h"
#include <QtWidgets/QApplication>

int main(int argc, char *argv[])
{
	QApplication a(argc, argv);
	TextTicker w;
	w.showFullScreen();
	return a.exec();
}
#pragma once

#include <QLabel>
#include <QTimer>

class TextTicker : public QLabel
{
	Q_OBJECT
public:
	TextTicker(QWidget *parent = 0);
	~TextTicker();
protected:
	void paintEvent(QPaintEvent *event);
	void updateIndex();//刷新
private:
	int m_charWidth;//每个字符所占的宽度(单位是像素)
	int m_curIndex;//从哪里开始显示当前字符串
	int m_length;//需要显示的字符串加了空格之后的字符串长度
	int m_maxCount;//窗体能容纳的最大字符数,即显示字符的个数
	QString m_showText;//需要显示的字符串(初始字符串--》加空格之后的字符串--》乘以2倍后的字符串)
};
#include "TextTicker.h"

TextTicker::TextTicker(QWidget *parent)
	: QLabel(parent)
{
	//设置背景颜色
	this->setStyleSheet("background-color:red");
	//设置字体大小
	QFont font;
	font.setPointSize(56);
	font.setBold(true);
	this->setFont(font);
	//设置字体颜色
	QPalette pa;
	pa.setColor(QPalette::WindowText, Qt::yellow);
	this->setPalette(pa);
	//给需要被显示的字符串赋初值
	m_showText = QStringLiteral("床前明月光,疑是地上霜,举头望明月,低头思故乡。床前明月光,疑是地上霜,举头望明月,低头思故乡。");
	//字符串初值后边加空格(当前一遍的尾巴和头需要同时显示的时候,加上少量空格,使显示更好看)
	m_showText += "          ";
	//获取添加空格后的需要显示的字符串的长度
	m_length = m_showText.size();
	//解决当前一遍的尾巴和头需要同时显示
	m_showText += m_showText;//需要打印的字符串 * 2
	//当前角码  
	m_curIndex = 0;
	//每个字符的宽度
	m_charWidth = fontMetrics().width("a");
	QTimer *timer = new QTimer(this);
	connect(timer, &QTimer::timeout, this, &TextTicker::updateIndex);
	timer->start(200);
}
TextTicker::~TextTicker()
{
}
void TextTicker::paintEvent(QPaintEvent *event)
{
	__super::paintEvent(event);
	this->setText(m_showText.mid(m_curIndex, m_maxCount));
}
void TextTicker::updateIndex()
{
	m_maxCount = width() / m_charWidth;
	update();
	m_curIndex++;
	if (m_curIndex >= m_length)
		m_curIndex = 0;
}

效果图如下所示:


参考文献:https://blog.csdn.net/u011417605/article/details/51211853



猜你喜欢

转载自blog.csdn.net/qq_24309981/article/details/80946167