文字跑马灯,支持循环次数。效果图如下
实现机制 就是通过计算文字宽带,然后用定时器不断移动文字显示位置,最后调用update触发paintEvent绘画文字显示。
1.跑马灯特效的QLabel类
定时器控制文本位置移动,其中m_posX代表文字初始位置
connect(&m_Timer, &QTimer::timeout, this, [=] {
if (isVisible()) {
m_PosX -= 2; //移动速度
if (parent) {
parent->update();
}
else {
update();
}
}
});
设置文本内容并启动定时器,m_speed代表文本移动总时间
void VMarqueeLabel::setText(const QString& text)
{
m_Timer.start(m_Speed);
QLabel::setText(text);
}
返回这个文本移动总时间给父类计算调用
int VMarqueeLabel::getSpeed()
{
return m_Speed;
}
paintEvent绘画控制文字显示
void VMarqueeLabel::paintEvent(QPaintEvent * evt)
{
QPainter painter(this);
//抗锯齿+平滑处理
painter.setRenderHint(QPainter::Antialiasing, true);
painter.setRenderHints(QPainter::SmoothPixmapTransform, true);
painter.translate(m_PosX, 0);
QTextDocument doc;
doc.setHtml(text());
int left = doc.documentLayout()->documentSize().width();
if (m_PosX <= -left) {
m_PosX = 50; //当最左边的文案完全消失在控件显示范围时,代表第一次跑马灯完成
}
doc.drawContents(&painter);
}
2.测试窗口类
/定时器控制跑马灯文字工作完后关闭窗口
m_TimeOut.setSingleShot(true);
connect(&m_TimeOut, &QTimer::timeout, this, &TxtMoveTest::stopTimer);
计算跑马灯所需时间启动定时器
void TxtMoveTest::toStartTimer(const QString &content, int count)
{
ui.label_txt->setText(content);
int timerNum = getTxtInfoForTimer(content, count);
m_TimeOut.start(timerNum);
}
获取文本长度,根据跑马灯循环次数计算出跑马灯工作下文本显示所需时间
int TxtMoveTest::getTxtInfoForTimer(const QString & content, int conut)
{
QTextDocument doc;
doc.setHtml(content);
int textWidth = doc.documentLayout()->documentSize().width();
int speed = ui.label_txt->getSpeed();
int result = (textWidth + 50) * speed * conut + speed * (conut - 1);
return result / 2;
}
还原窗口
void TxtMoveTest::initWidget()
{
ui.label_txt->clear();
}
结束窗口显示
void TxtMoveTest::stopTimer()
{
if (m_TimeOut.isActive())
m_TimeOut.stop();
initWidget();
close();
}
3.测试实例
m_moveTxt = new TxtMoveTest(this);
QString m_content = QStringLiteral("<font size=4 color=#fff>%1</font>").arg(QStringLiteral("彼岸花开开彼岸,花开叶落永不见。因果注定一生死,三生石上前生缘。"));
m_moveTxt->toStartTimer(m_content, 2);
m_moveTxt->show();