IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> QT 实现跑马灯 -> 正文阅读

[C++知识库]QT 实现跑马灯

目录

背景

一、LED设计

1、头文件

2、源文件

二、跑马灯LED位置放置设计

三、实现跑马灯简要代码

1、头文件

2、源文件

3、ui文件

四、效果展示

?参考


背景

????????应项目需求,需要实现一个体现系统运行状态的类似跑马灯效果一样的控件,跑马灯还是本科电子工艺实习期间焊接电路板的时候接触过,初听要用qt实现这个效果,还觉得挺有意思的。开始是调研,理解了一篇博客分享的点阵LED,开始着手实现,最终实现了一个动态的显示状态的小控件。现分享一个实现该控件的一个简要思路。单个LED的设计完全是借鉴过来的,实现跑马灯的效果,主要的工作体现在灯的放置上,也算是存在一个小小的算法设计,虽然这是一个小功能,但是实现之后还是挺有成就感的,特分享出来,供他人做自定义控件的时候借鉴。

一、LED设计

? ? ? ? ?该部分完全借鉴于qt之led(点阵)控件类设计_求知者先的博客-CSDN博客_qt模拟led点阵显示

1、头文件

? ? ? ? ?rgb_led.h

#ifndef __H_RGB_LED_H__
#define __H_RGB_LED_H__

#include <QWidget>
#include <QPainter>

enum LedShape
{
    circular,
    square,
};

class RGBLed : public QWidget
{
    Q_OBJECT
public:
    explicit RGBLed(QWidget *parent = nullptr);

    void setShape(LedShape shape);
    void setShapeToCir();       //设置灯为圆状
    void setShapeToSqu();       //设置灯为方状

    void setColor(QColor color);    //设置led颜色
    void setColor(unsigned char red, unsigned char green, unsigned char blue);
    QColor getLedColor();   //获取led颜色

    //设置led灯大小,此处为绝对大小,即限制了最大最小,直接固定在一个一个大小
    void setFixedSize(int width, int hight); //设置led大小
    void unFixedSize(int miniWidth = 0,int miniHight = 0);  //取消固定大小,一般不建议使用。

    //led有两种状态,一种是点亮状态,正常显示设置的颜色,第二种是未点亮(熄灭)的状态,熄灭状态的颜色也可以设置,一般为黑灰色。
    bool isLight();     //判断是否点亮
    void setLight(bool light = true);  //设置是否点亮
    void setUnlightColor(QColor color = QColor(50,50,50));  //设置未点亮状态下颜色

    //hsv格式转rgb格式,静态模式,外界可直接使用
    static void HSVtoRGB(unsigned char& out_r, unsigned char& out_g, unsigned char& out_b, int h, int s, int v);
signals:

private:
    void paintEvent(QPaintEvent *paintEvent) override;
    void mouseReleaseEvent(QMouseEvent *event) override;

    QColor          mColor;         //led灯颜色
    LedShape        mShape;         //led灯形状
    bool            lightFlag;      //灯是否点亮
    QColor          unlightColor;   //熄灭状态的颜色,默认(50,50,50)

};

#endif // __H_RGB_LED_H__

2、源文件

? ? ? ? ? rgb_led.cpp

#include "rgb_led.h"

RGBLed::RGBLed(QWidget *parent) :
    QWidget(parent)
    ,mShape(square)
    ,lightFlag(true)
    ,unlightColor(QColor(50,50,50))
{
    setFixedSize(30,30);
    mColor = unlightColor;
}

void RGBLed::setShape(LedShape shape)
{
    mShape = shape;
}

void RGBLed::setShapeToCir()
{
    mShape = circular;
}

void RGBLed::setShapeToSqu()
{
    mShape = square;
}

void RGBLed::setFixedSize(int width,int hight)
{
    this->setMaximumSize(width,hight);
    this->setMinimumSize(width,hight);
    update();
}

void RGBLed::unFixedSize(int miniWidth, int miniHight)
{
    this->setMaximumSize(10000,10000);
    this->setMinimumSize(miniWidth,miniHight);
}

bool RGBLed::isLight()
{
    return lightFlag;
}

void RGBLed::setLight(bool light)
{
    lightFlag = light;
}

void RGBLed::setUnlightColor(QColor color)
{
    unlightColor = color;
}

void RGBLed::setColor(QColor color)
{
    mColor = color;
    update();
}
void RGBLed::setColor(unsigned char red,unsigned char green,unsigned char blue)
{
    mColor = QColor(red,green,blue);
    update();
}

QColor RGBLed::getLedColor()
{
    return mColor;
}

void RGBLed::paintEvent(QPaintEvent *paintEvent)
{
    Q_UNUSED(paintEvent);
    QPainter painter(this);

    int edgeWidth = 1;
    int width = this->width();
    int hight = this->height();

    painter.setPen(QPen(QColor(255, 255, 255)));
    QBrush brush(QColor(255,255,255));
    painter.setBrush(brush);

    //绘制中心显色区域
    if(lightFlag)
        painter.setBrush(mColor);
    else
        painter.setBrush(unlightColor);

    if(mShape == square)
        painter.drawRect(QRectF(edgeWidth, edgeWidth, width-edgeWidth, hight-edgeWidth));
    else if(mShape == circular)
        painter.drawEllipse(QRectF(edgeWidth, edgeWidth, width-edgeWidth, hight-edgeWidth));

    painter.end();
}

void RGBLed::mouseReleaseEvent(QMouseEvent *event)
{
    lightFlag = !lightFlag;
    update();
}

void RGBLed::HSVtoRGB(unsigned char& out_r, unsigned char& out_g, unsigned char& out_b, int h, int s, int v)
{
    // convert from HSV/HSB to RGB color
    // R,G,B from 0-255, H from 0-260, S,V from 0-100
    // ref http://colorizer.org/
    // The hue (H) of a color refers to which pure color it resembles
    // The saturation (S) of a color describes how white the color is
    // The value (V) of a color, also called its lightness, describes how dark the color is
    int i;
    float RGB_min, RGB_max;
    RGB_max = v*2.55f;
    RGB_min = RGB_max*(100 - s)/ 100.0f;

    i = h / 60;
    int difs = h % 60; // factorial part of h
    float RGB_Adj = (RGB_max - RGB_min)*difs / 60.0f; // RGB adjustment amount by hue

    switch (i) {
    case 0:
        out_r = RGB_max;
        out_g = RGB_min + RGB_Adj;
        out_b = RGB_min;
        break;
    case 1:
        out_r = RGB_max - RGB_Adj;
        out_g = RGB_max;
        out_b = RGB_min;
        break;
    case 2:
        out_r = RGB_min;
        out_g = RGB_max;
        out_b = RGB_min + RGB_Adj;
        break;
    case 3:
        out_r = RGB_min;
        out_g = RGB_max - RGB_Adj;
        out_b = RGB_max;
        break;
    case 4:
        out_r = RGB_min + RGB_Adj;
        out_g = RGB_min;
        out_b = RGB_max;
        break;
    default:  // case 5:
        out_r = RGB_max;
        out_g = RGB_min;
        out_b = RGB_max - RGB_Adj;
        break;
    }
}

二、跑马灯LED位置放置设计

? ? ? ? ? ? 如下图所示,实现一个16*16(rows=16,cols=16)的矩形跑马灯,需要考虑两个问题。

?????????(1)由于灯要交替闪烁,相邻的灯之间需要存在联系,比如此时是奇数灯亮,偶灯等灭;下一个时刻是偶数灯亮,奇数灯灭。所以我们需要把灯按照循环的顺序放入到一个列表中。列表的长度为:total = (rows+cols-2)*2。

? ? ? ? (2)需要确定列表中排在n的灯与它所处位置之间的关系。为了解决这个问题,灯的列表分成s1、s2、s3、s4四段,它们的规律如下:

????????????????s1[0: (cols-2)]段放置位置的横坐标为row=0,纵坐标col从0到(cols-2)依次递增。

? ? ? ? ? ? ? ? s2[(cols-1): (cols+rows-3)]段放置位置的横坐标row从0到(rows-2)依次递增,纵坐标col=cols-1;

????????????????s3[(cols+rows-2): (2*rows-2+cols-2)]段放置位置的横坐标row=?rows -1,纵坐标col从cols-1到1依次递增;?

???????? ???????s4[(2*rows+cols-3) : (2*rows+2*cols - 5)]段放置位置的横坐标row从(rows-1)到1依次递减,纵坐标col=0;

? ? ? ? ? ? ?所以,16*16的跑马灯分成如下4段:

? ? ? ? ? ? ????????? s1:0~14

? ? ? ? ? ????????? ? s2:15~29

? ? ? ? ? ? ? ????????s3:30~44

? ? ? ? ? ? ????????? s4:45~49

? ? ? ? ? ? ?具体对应灯的位置如下图所示。

三、实现跑马灯简要代码

? ? ? ? ? ? 主要包括初始化设置(灯的属性设置和进行放置布局)和使用一个定时器控制灯的亮灭两个部分。

1、头文件

#ifndef __H_DYNAMIC_STATUS_H__
#define __H_DYNAMIC_STATUS_H__

#include <QApplication>
#include <QMainWindow>
#include <QTimer>
#include "rgb_led.h"
#include "statuslabel.h"

namespace Ui {
class DynamicStatus;
}

class DynamicStatus : public QMainWindow
{
    Q_OBJECT

public:
    explicit DynamicStatus(QWidget *parent = 0);
    ~DynamicStatus();

    void init();

public slots:
    void OnLedStatusUpdateTimer();

private:
    Ui::DynamicStatus *ui_;
    QList<RGBLed*> led_list_;
    QTimer led_status_update_timer_;
    bool change_status_;
};

2、源文件

#include "dynamic_status.h"
#include "ui_dynamic_status.h"
#include <QGridLayout>
#include <QTimer>
#include <QDebug>

DynamicStatus::DynamicStatus(QWidget *parent) :
    QMainWindow(parent),
    ui_(new Ui::DynamicStatus),
    change_status_(true)
{
    ui_->setupUi(this);
    init();  
}

DynamicStatus::~DynamicStatus()
{
    delete ui_;
}

void DynamicStatus::init()
{
    int rows = 16; int cols = 16;
    int total = (rows + cols - 2) * 2;
    int s1_col_start =0;
    int s2_row_start =0;
    int s3_col_start = cols -1;
    int s4_row_start = rows -1;
    for(int i = 0; i < total; i++){
        RGBLed* led = new RGBLed;
        led->setShapeToCir();
        led->setFixedSize(30,30);
        led->setUnlightColor(QColor(0,0,0));
        led_list_.append(led);
        if(i < cols -1) {
            ui_->gridLayout->addWidget(led,0, s1_col_start++);
        } else if (i < (cols + rows -2)) {
            ui_->gridLayout->addWidget(led, s2_row_start++, cols - 1);
        } else if (i < (2*cols + rows -3)) {
            ui_->gridLayout->addWidget(led, rows -1 , s3_col_start--);
        } else {
            ui_->gridLayout->addWidget(led, s4_row_start--, 0);
        }
    }

    connect(&led_status_update_timer_, &QTimer::timeout, this, &DynamicStatus::OnLedStatusUpdateTimer);
    qDebug() << "DynamicStatus::start(): led_list_.size() = " << led_list_.size() ;
    led_status_update_timer_.start(1000);
}

void DynamicStatus::OnLedStatusUpdateTimer()
{
    static unsigned char offset = 0;
    offset = offset+3;
    for(int i = 0;i < led_list_.size();i ++)
    {
        unsigned char r;
        unsigned char g;
        unsigned char b;
        unsigned char h = i+offset;
        RGBLed::HSVtoRGB(r,g,b,h,100,75);
        if(change_status_) {
            if(i%2 == 0) {
                led_list_.at(i)->setColor(0,0,0);
            } else {
                led_list_.at(i)->setColor(r,255,b);
            }
        } else {
            if(i%2 == 0) {
                led_list_.at(i)->setColor(r,255,b);
            } else {
                led_list_.at(i)->setColor(0,0,0);
            }
        }
    }
    change_status_ = ! change_status_;
}

3、ui文件

? ? ? ? 创建一个普通的ui界面,在界面上添加gridLayout控件即可。此处略。

四、效果展示

? ? ? ? ? ? ?录屏,制作成gif,展示,效果如我所想,还不错。

?参考

1、RGBLed class is from CSDN: https://blog.csdn.net/weixin_42887343/article/details/115348953

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-05-10 11:40:56  更:2022-05-10 11:43:12 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/20 20:57:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码