• Qt实战14.告警信息滚动轮播控件


    1 需求描述

    做一个独立的控件,该控件能够滚动轮播报警信息,告警信息分为一般、严重、危险三个等级,分别用不同颜色做标记。

    2 设计思路

    做滚动轮播效果,优先想到Qt的动画框架,同时考虑到图形视图框架的易用性,实现上应该会简单不少,所以该控件会使用图形视图框架并结合动画框架实现。

    • 每一条告警信息用QGraphicsTextItem表示
    • 由于整体要使用动画轮播,所有的QGraphicsTextItem会添加到一个QGraphicsItemGroup中,方便做整体动画
    • 动画使用QVariantAnimation即可,毕竟轮播只是改变了QGraphicsItemGroup的y坐标
    • 为了能够适应窗口大小的变化,需要动态调整场景的大小和动画参数

    3 代码实现

    控件为QGraphicsView的子类,设定了自定义的场景类,场景封装在控件内部,场景提供了必要的接口,例如添加、清空告警信息:

    3.1 AlarmHistoryScene.h

    class AlarmHistoryScene : public QGraphicsScene
    {
        Q_OBJECT
    
    public:
        explicit AlarmHistoryScene(QObject *parent = 0);
    
        void addAlarmText(WarningLevel level, const QString &alarm);
        void clear();
    
    private:
        void updateAnimation();
    
    private:
        QStringList m_alarmList;
        QGraphicsItemGroup *m_pItemGroup = nullptr;
        QVariantAnimation *m_pAnimation = nullptr;
    };
    

    addAlarmText添加告警信息接口,clear清空告警信息,updateAnimation会在初次启动或窗口大小变化时自动调用。

    3.2 AlarmHistoryScene.cpp

    AlarmHistoryScene::AlarmHistoryScene(QObject *parent) : QGraphicsScene(parent)
    {
        m_pItemGroup = new QGraphicsItemGroup();
    
        addItem(m_pItemGroup);
        m_pItemGroup->setPos(0, 0);
    
        connect(this, &AlarmHistoryScene::sceneRectChanged, this, &AlarmHistoryScene::updateAnimation);
    }
    
    void AlarmHistoryScene::addAlarmText(WarningLevel level ,const QString &alarm)
    {
        QString detail = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")
                .append(QStringLiteral(":"))
                .append(alarm);
    
        QGraphicsTextItem *item = new QGraphicsTextItem(detail);
    
        QFont font;
        font.setFamily("System");
        font.setPixelSize(12);
    
        item->setFont(font);
        switch (level) {
        case WarningLevel::Normal:
            item->setDefaultTextColor(QColor(227, 207, 87));
            break;
        case WarningLevel::Serious:
            item->setDefaultTextColor(QColor(243, 130, 19));
            break;
        case WarningLevel::Danger:
            item->setDefaultTextColor(QColor("red"));
            break;
        default:
            break;
        }
    
        int count = m_pItemGroup->childItems().count();
    
        item->setPos(0, m_pItemGroup->y() + count * (font.pixelSize() + 2));
        m_pItemGroup->addToGroup(item);
    
        updateAnimation();
    }
    

    根据日志等级实例化QGraphicsTextItem并添加到m_pItemGroup中,再更新下动画,这里没啥可说的。

    void AlarmHistoryScene::clear()
    {
        if (m_pAnimation) {
            m_pAnimation->stop();
            m_pAnimation->deleteLater();
            m_pAnimation = nullptr;
        }
    
        m_pItemGroup->setPos(0, 0);
        auto list = m_pItemGroup->childItems();
        int count = list.count();
        for (int i = 0; i < count; ++i) {
            auto item = list.at(i);
            m_pItemGroup->removeFromGroup(item);
            removeItem(item);
            delete item;
        }
    }
    

    这里主要是关闭动画,并清空所有告警信息。

    void AlarmHistoryScene::updateAnimation()
    {
        if (m_pAnimation) {
            m_pAnimation->stop();
            m_pAnimation->deleteLater();
            m_pAnimation = nullptr;
        }
    
        m_pAnimation = new QVariantAnimation(this);
        connect(m_pAnimation, &QVariantAnimation::valueChanged, this, [=](const QVariant &value) {
            m_pItemGroup->setPos(0, value.toDouble());
        });
        m_pAnimation->setLoopCount(-1);
    
        qreal sceneHeight = this->sceneRect().height();
        m_pItemGroup->setPos(0, sceneHeight);
    
        m_pAnimation->setDuration((sceneHeight + m_pItemGroup->boundingRect().height()) * 12);
        m_pAnimation->setStartValue(sceneHeight);
        m_pAnimation->setEndValue(-m_pItemGroup->boundingRect().height());
        m_pAnimation->start();
    }
    

    更新动画,作用于m_pItemGroup,轮播只需要改变y坐标值,所以使用QVariantAnimation即可实现。

    3.3 AlarmHistoryView.cpp

    场景封装在视图内部,这里需要根据视图大小动态调整场景大小,以便使动画适应窗口。

    AlarmHistoryView::AlarmHistoryView(QWidget *parent) : QGraphicsView(parent)
    {
        m_pScene = new AlarmHistoryScene(this);
        setScene(m_pScene);
    
        setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    }
    
    void AlarmHistoryView::addAlarmText(WarningLevel level, const QString &alarm)
    {
        m_pScene->addAlarmText(level, alarm);
    }
    
    void AlarmHistoryView::resizeEvent(QResizeEvent *event)
    {
        QGraphicsView::resizeEvent(event);
        m_pScene->setSceneRect(0, 0, this->size().width(), this->size().height());
    }
    

    好啦,主要代码就这么多了,还是挺简单的。

    4 总结

    Qt图形视图框架异常强大,结合动画框架能够实现很多酷炫效果,这里也只用到了一点点皮毛,多看看Qt的Demo程序会有很多意外收获,一般人我不告诉他,哈哈。溜了溜了。。。新年快乐!

    5 下载

    示例代码

  • 相关阅读:
    python2.7 目录下没有scripts
    pycharm配置appium 提示unsrsloved reference
    查看cookie的快捷方法
    在线linux 平台
    selenium配置Chrome驱动
    ImportError: sys.meta_path is None, Python is likely shutting down
    基本控件文档-UISwitch属性---iOS-Apple苹果官方文档翻译
    基本控件文档-UISlider属性---iOS-Apple苹果官方文档翻译
    基本控件文档-UISegment属性----iOS-Apple苹果官方文档翻译
    基本控件文档-UILabel属性---iOS-Apple苹果官方文档翻译
  • 原文地址:https://www.cnblogs.com/luoxiang/p/15849231.html
Copyright © 2020-2023  润新知