【Qt开发】显示类控件(二)-> QLCDNumber

发布于:2025-09-12 ⋅ 阅读:(26) ⋅ 点赞:(0)

目录

1 -> 概览

2 -> 核心属性

3 -> 核心功能与特性

4 -> 经典应用场景

5 -> 优点和局限性

6 -> 代码示例:倒计时

7 -> 总结


1 -> 概览

在构建现代软件界面时,开发者不仅追求功能强大,也日益注重视觉表现和用户体验。有时,为了契合特定主题(如工业控制、音频播放器、科学实验模拟或经典游戏),我们需要一种能够瞬间唤起用户时代感或专业感的界面元素。Qt 框架中的 QLCDNumber 控件,正是为此而生的经典组件。

QLCDNumber 是一个用于显示数字的小部件。其核心设计理念是模拟老式的七段数码管(Seven-segment display)或点阵式液晶显示(LCD)效果。这种显示方式在计算器、电子钟表、仪器仪表等领域极为常见。它不像普通的标签QLabel那样直接渲染字体,而是通过点亮特定的“段”来组合成数字或少量字母,从而呈现出一种独特的、带有浓厚技术复古风的视觉效果。

2 -> 核心属性

属性 说明
intValue QLCDNumber 显示的数字值(int)
value

QLCDNumber 显示的数字值(double)

和 intValue 是联动的

例如给 value 设为 1.5,intValue 的值就是 2

另外,设置 value 和 intValue 的方法名字为 display,而不是 setValue 或者 setIntValue

digitCount 显示几位数字
mode

数字显示形式

  1. QLCDNumber::Dec:十进制模式,显示常规的十进制数字
  2. QLCDNumber::Hex:十六进制模式,以十六进制格式显示数字
  3. QLCDNumber::Bin:二进制模式,以二进制格式显示数字
  4. QLCDNumber::Oct:八进制模式,以八进制格式显示数字

只有十进制的时候才能显示小数点后的内容

segmentStyle

设置显示风格

  1. QLCDNumber::Flat:平面的显示风格,数字呈现在一个平坦的表面上
  2. QLCDNumber::Outline:轮廓显示风格,数字具有清晰的轮廓和阴影效果
  3. QLCDNumber::Filled:填充显示风格,数字被填充颜色并与背景区分开
smallDecimalPoint 设置比较小的小数点

3 -> 核心功能与特性

1. 数字显示

QLCDNumber 最主要的功能是清晰地显示整型或浮点型数字。它可以自动处理数字的对齐方式(通常为右对齐),并支持显示一个额外的小数点。

2. 数码位数设置

开发者可以预先设定控件能够显示的数码位数。当数字的整数部分超出设定位数时,控件会显示溢出(通常为一连串的“E”或类似提示);当数字位数不足时,则会在左侧以零或空格进行填充,这非常符合传统电子设备的显示习惯。

3. 多种显示模式

控件提供了几种经典的显示模式,允许开发者根据整体UI风格进行选择:

  • 十六进制(Hex):可以显示数字0-9和字母A-F,适用于需要显示内存地址等信息的场景。

  • 十进制(Dec):最常用的模式,用于显示常规数字。

  • 八进制(Oct):显示八进制数字。

  • 二进制(Bin):以二进制形式显示数字,每一位都清晰可见。

4. 视觉风格定制

  • 段样式(Segment Style)QLCDNumber 允许选择数码管的视觉风格,例如“轮廓(Outlined)”、“填充(Filled)”和“扁平(Flat)”,以适应不同深浅的背景色,确保显示清晰易读。

  • 颜色:虽然传统LCD是单色的(通常是深色背景上的亮色数字),但Qt允许你设置任意颜色作为数字(“段”)的颜色和背景色,从而创造出诸如暗黑模式下的绿色数字、复古的琥珀色或现代感的蓝色效果。

5. 溢出与特殊值处理

当显示的数字超出控件范围或为非数值(NaN)时,控件会有一个明确的视觉指示(如显示“E”),这为调试和用户提示提供了便利。

4 -> 经典应用场景

  • 计时器/秒表:显示经过的时间或剩余时间,是 QLCDNumber 最经典的应用。

  • 媒体播放器:显示当前播放进度和总时长,完美复刻了传统音响设备的UI。

  • 计算器应用:作为计算结果的显示区域,是其最原始、最自然的用途。

  • 工业控制与仪表盘模拟:显示温度、转速、压力等实时数据,营造出专业的工业HMI(人机交互界面)氛围。

  • 游戏界面:在赛车游戏中显示速度,在模拟游戏中显示分数或资源数量,能有效增强游戏的特定时代感或科技感。

  • 系统监控工具:显示CPU占用率、内存使用量等数值信息。

5 -> 优点和局限性

优点

  • 风格独特:能快速为应用界面确立特定的视觉基调,这是使用标准字体无法轻易实现的。

  • 清晰可读:在高亮或大尺寸显示下,LCD风格的数字非常醒目,易于远距离或快速识别。

  • 轻量级:作为Qt内置控件,它非常高效,无需依赖外部资源。

局限性

  • 显示内容有限:基本上只能用于显示数字和极有限的字母(A-F, ‘E’等),无法显示普通文本或复杂符号。

  • 风格固定:其外观是高度风格化的,如果与应用的整体现代扁平设计风格不搭,则会显得格格不入。它更适合作为“点睛之笔”而非主要信息展示控件。

6 -> 代码示例:倒计时

1. 在界面上创建一个 QLCDNumber,初始值设为 10

objectName 设为默认

2. 修改 widget.h 代码,创建一个 QTimer 成员,和一个 handle 函数

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    void handle();

private:
    Ui::Widget *ui;
    QTimer* timer;
};
#endif // WIDGET_H

3. 修改 widget.cpp,在构造函数中初始化 QTimer

  • QTimer 表示定时器。通过 start 方法启动定时器之后,就会每隔一定周期,触发一次 QTimer::timeout 信号。
  • 使用 connect 把 QTimer::timeout 信号和 Widget::handle 连接起来,意味着每次触发 QTimer::timeout 都会执行 Widget::handle。
#include "widget.h"
#include "ui_widget.h"

#include <QDebug>
#include <QTimer>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 设置初始值
    ui->lcdNumber->display(20);

    // 创建一个 QTimer 实例
    timer = new QTimer(this);

    // 把 QTimer 的 timeout 信号和咱们自己的槽函数进行连接
    connect(timer, &QTimer::timeout, this, &Widget::handle);

    // 启动定时器, 参数是触发 timeout 的周期. 单位是 ms
    timer->start(1000);

}

Widget::~Widget()
{
    delete ui;
}

4. 修改 widget.cpp,实现 handle

  • 通过 intValue 获取到 QLCDNumber 内部的数值。
  • 如果 value 的值归 0 了,就停止 QTimer。接下来 QTimer 也就不会触发 timeout 信号了。
#include "widget.h"
#include "ui_widget.h"

#include <QDebug>
#include <QTimer>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 设置初始值
    ui->lcdNumber->display(20);

    // 创建一个 QTimer 实例
    timer = new QTimer(this);

    // 把 QTimer 的 timeout 信号和咱们自己的槽函数进行连接
    connect(timer, &QTimer::timeout, this, &Widget::handle);

    // 启动定时器, 参数是触发 timeout 的周期. 单位是 ms
    timer->start(1000);

}

Widget::~Widget()
{
    delete ui;
}

void Widget::handle()
{
    // 测试
    // qDebug() << "handle";
    int value = ui->lcdNumber->intValue();
    if (value <= 0)
    {
        timer->stop();
        return;
    }

    ui->lcdNumber->display(value - 1);

}

5. 执行程序,可以看到每隔一秒钟,显示的数字就减少 1

针对上述代码,存在两个问题:

1. 上述代码如果直接在 Widget 构造函数中,通过一个循环 + sleep 的方式是否可以呢?

int value = ui->lcdNumber->intValue();
    while (true) 
    {
        std::this_thread::sleep_for(std::chrono::seconds(1));
        if (value <= 0) 
        {
            break;
        }
        
        ui->lcdNumber->display(value - 1);
    }

显然,这个代码是不行的。循环会使 Widget 的构造函数无法执行完毕,此时的界面是不能正确构造和显示的。

2. 上述代码如果是在 Widget 构造函数中,另起一个线程,在新线程中完成 循环 + sleep 是否可以呢?

std::thread t([this]() 
    {
        int value = this->ui->lcdNumber->intValue();
        while (true) 
        {
            std::this_thread::sleep_for(std::chrono::seconds(1));
            if (value <= 0) 
            {
                break;
            }
            
            this->ui->lcdNumber->display(value - 1);
        }
    });

这个代码同样是不行的。Qt 中规定,任何对于 GUI 上内容的操作,必须在 主线程 中完成。像 Widget 构造函数,以及 connect 连接的 slot 函数,都是在主线程中调用的。而自己创建的线程则不是。

当我们自己的线程中尝试对界面元素进行修改时,Qt 程序往往会直接崩溃。

这样的约定主要是因为 GUI 中的状态往往是牵一发动全身的,修改一个地方,就需要同步的对其他内容进行调整。

比如调整了某个元素的尺寸,就可能影响到内部的文字位置,或者其他元素的位置。这里一连串的修改,都是需要按照一定的顺序来完成的。

由于多线程执行的顺序无法保障,因此,Qt 从根本上禁止了其他线程修改 GUI 状态,避免后续的一系列问题。

综上所述,使用定时器,是实现上述功能的最合理方案。

7 -> 总结

QLCDNumber 是Qt工具箱中一个极具特色的控件。它远不止是一个简单的数字显示器,更是一个强大的 “氛围营造者”。当你需要为用户界面添加一丝复古科技感、专业仪器感或清晰的数字焦点时,QLCDNumber 是一个简单而高效的选择。它省去了开发者用图像自己绘制数字的麻烦,通过简单的属性设置就能达到出色的视觉效果,是 Qt 为丰富开发者界面表达能力所提供的一件精致而实用的工具。


感谢各位大佬支持!!!

互三啦!!!


网站公告

今日签到

点亮在社区的每一天
去签到