您当前的位置: 首页 > 

龚建波

暂无认证

  • 3浏览

    0关注

    312博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

QLabel绘制滚动文本

龚建波 发布时间:2020-06-05 23:19:16 ,浏览量:3

实现思路

绘制滚动文本是个很简单的事,只需要用定时器累计一个文本坐标偏移量,然后 update ,在 paintEvent 里把文本画出来。

Qt 定时刷新可以用(可能还有其他方式):

  • QObject的startTimer配合paintEvent;
  • QBasicTimer配合paintEvent;(源码中很多都用的这个类,我也就用的这个类了)
  • QTimer;
  • QTimeLine;
  • QAnimation;(如果除了滚动还有颜色等动画,建议用动画组实现)

paintEvent 里 QPainter 的设置默认是被样式表影响的,所以我在样式表里设置的颜色和字体。

获取文本高度的时候还有个坑,就是 Qt 文本的 height() 包含基线往上和往下两部分,但是不一定代表字体的真实信息:

我绘制的时候减去了基线底部距离 descent 才显示正常了,不然就没上下居中对齐(直接用 ascent 感觉有点偏),也可以用 Qt5.8 引入的 capHeight:

    /*const int text_height = painter.fontMetrics().capHeight();
    const int text_y = (height()+text_height) / 2;*/
    const int text_height = painter.fontMetrics().height();
    const int text_y = (height()+text_height) / 2-painter.fontMetrics().descent();

实现基本功能之后也可以进行扩展,如颜色变换,在某一位置暂留,多条文本滚动等。 

最终实现

实现效果:

代码链接:

github链接:https://github.com/gongjianbo/MyTestCode/tree/master/Qt/ScrollLabel

主要代码:

#ifndef SCROLLLABEL_H
#define SCROLLLABEL_H

#include 
#include 

//滚动文字的label
class ScrollLabel : public QLabel
{
    Q_OBJECT
public:
    enum ScrollDirection{ //滚动方向
        RightToLeft=1,
        LeftToRight=2
    };
public:
    explicit ScrollLabel(QWidget *parent = nullptr);

    //滚动方向
    ScrollLabel::ScrollDirection getDirection() const;
    void setDirection(ScrollLabel::ScrollDirection direction);

    //刷新间隔
    int getInterval() const;
    void setInterval(int interval);

protected:
    //basictimer定时器触发
    void timerEvent(QTimerEvent *event) override;
    //绘制
    void paintEvent(QPaintEvent *event) override;
    //大小变化时重新计算
    void resizeEvent(QResizeEvent *event) override;

private:
    //滚动定时器
    //也可以使用QTimer QTimeLine QAnimation等实现
    QBasicTimer scrollTimer;
    int interval=20;
    //偏移量
    int offset=0;
    int textWidth=0;
    int labelWidth=0;
    //默认右往左
    ScrollDirection direction=RightToLeft;
};

#endif // SCROLLLABEL_H
#include "ScrollLabel.h"

#include 
#include 
#include 
#include 

#include 

ScrollLabel::ScrollLabel(QWidget *parent)
    : QLabel(parent)
{
    //启动定时器,触发this的timerevent
    scrollTimer.start(interval,this);
}

ScrollLabel::ScrollDirection ScrollLabel::getDirection() const
{
    return direction;
}

void ScrollLabel::setDirection(ScrollLabel::ScrollDirection direction)
{
    if(this->direction!=direction){
        this->direction=direction;
        offset=0;
    }
}

int ScrollLabel::getInterval() const
{
    return interval;
}

void ScrollLabel::setInterval(int interval)
{
    if(this->interval!=interval){
        this->interval=interval;
        scrollTimer.start(interval,this);
    }
}

void ScrollLabel::timerEvent(QTimerEvent *event)
{
    //定时器timeout
    if(event->timerId()==scrollTimer.timerId()){
        event->accept();
        ++offset;
        if(offset>textWidth+labelWidth){
            offset=0;
        }
        update();
    }else{
        QLabel::timerEvent(event);
    }
}

void ScrollLabel::paintEvent(QPaintEvent *event)
{
    event->accept();

    QPainter painter(this);
    const int text_width = painter.fontMetrics().width(text());
    //字体绘制坐标为左下角,y值就是 labelheight-(labelheight-textheight)/2
    //因为取的字体高度还受基线影响,height=descent+ascent,这里去掉descent
    //也可以用Qt5.8提供的capHeight
    /*const int text_height = painter.fontMetrics().capHeight();
    const int text_y = (height()+text_height) / 2;*/
    const int text_height = painter.fontMetrics().height();
    const int text_y = (height()+text_height) / 2-painter.fontMetrics().descent();
    if (textWidth != text_width && text_width > 0) {
        textWidth = text_width;
        offset = 0;
    }else {
        if(direction==RightToLeft){
            //从右往左
            painter.drawText(labelWidth - offset, text_y, text());
        }else{
            //从左往右
            painter.drawText(offset - textWidth, text_y, text());
        }
    }
}

void ScrollLabel::resizeEvent(QResizeEvent *event)
{
    const int old_width = event->oldSize().width();
    const int new_width = event->size().width();
    if (new_width > 10) {
        labelWidth = new_width;
        //新宽度更小,就重置偏移
        if (new_width < old_width) {
            offset = 0;
        }
    }
    QLabel::resizeEvent(event);
}

 

 

关注
打赏
1655829268
查看更多评论
立即登录/注册

微信扫码登录

0.7415s