本文专栏Qt作者主页努力努力再努力wz今日博客励志语录别怕慢怕的是你一边走一边怀疑这条路结果连慢都没攒下来。思维导图引入在此前的学习中我们已经了解了 Qt 中的一些常用控件包括按钮类控件和标签类控件。通过这些内容我们初步认识了 Qt 控件的基本使用方式以及控件在界面显示、用户交互和信号槽机制中的作用。本文将继续围绕 Qt 常用控件展开进一步学习其他典型控件的使用方式并结合实际代码分析其常见属性、信号槽连接方式以及在界面开发中的应用场景。QLCDNumber 数字显示控件从基础显示控制到倒计时案例QLCDNumberLCD 数字显示控件的基本使用与显示控制首先要介绍的显示类控件是QLCDNumber即LCD 数字显示控件。从功能定位上来看QLCDNumber和前面学习过的QLabel有一定相似之处它们都可以在界面中展示内容。不过二者的侧重点并不相同QLabel更偏向通用文本或图片展示可以显示普通字符串、富文本以及图片而QLCDNumber则更侧重于数值展示它会以类似电子表、计算器或数码管的 LCD 风格显示数字。在实际开发中QLCDNumber的外观属性既可以在 Qt Designer 中通过可视化方式进行设置也可以通过 C 代码进行控制。例如可以设置它的数字位数、显示模式、小数点样式等属性。对于QLCDNumber来说设置当前显示内容的核心接口是display()。该接口提供了多个重载版本既可以接收整数也可以接收浮点数还可以接收字符串形式的内容并将其以 LCD 数字风格显示到界面中。ui-lcdNumber-display(10);// 显示整数ui-lcdNumber-display(3.14);// 显示浮点数ui-lcdNumber-display(12:30);// 显示部分 LCD 风格支持的字符串需要注意的是虽然display()可以接收字符串参数但QLCDNumber并不是通用字符串显示控件。由于它采用 LCD 数码管风格进行绘制因此只能显示数字以及少量适合数码管表示的字符例如负号、小数点、冒号、部分英文字母等。如果传入了不支持的字符这些字符会被替换为空格。因此如果只是普通文本展示更适合使用QLabel如果是数字、时间、计数器、倒计时等内容展示则更适合使用QLCDNumber。除了设置显示值之外QLCDNumber还可以控制数值的显示进制。它支持十进制、十六进制、八进制和二进制显示模式ui-lcdNumber-setMode(QLCDNumber::Dec);// 十进制ui-lcdNumber-setMode(QLCDNumber::Hex);// 十六进制ui-lcdNumber-setMode(QLCDNumber::Oct);// 八进制ui-lcdNumber-setMode(QLCDNumber::Bin);// 二进制也可以使用对应的槽函数来切换显示模式ui-lcdNumber-setDecMode();ui-lcdNumber-setHexMode();ui-lcdNumber-setOctMode();ui-lcdNumber-setBinMode();需要注意的是QLCDNumber虽然可以通过display(double)接收浮点数但只有在十进制模式下才会正常显示小数部分。当控件处于十六进制、八进制或二进制模式时传入浮点数本身不会导致接口调用错误但控件会按照该数值对应的整数形式进行进制显示因此不会展示小数部分。对于显示位数QLCDNumber提供了setDigitCount()接口。该接口用于设置控件当前能够显示的数字位数例如ui-lcdNumber-setDigitCount(5);这里的5表示控件最多显示 5 个数字位而不是表示小数点后保留 5 位。如果传入display()的内容超出了当前digitCount所能容纳的范围控件就无法完整显示该内容并可能触发overflow()信号。例如ui-lcdNumber-setDigitCount(5);ui-lcdNumber-display(12345);// 可以完整显示ui-lcdNumber-display(123456);// 超出 5 位可能触发 overflow()如果显示的是小数还需要结合setSmallDecimalPoint()来理解。该接口用于控制小数点的显示方式ui-lcdNumber-setSmallDecimalPoint(true);当参数为true时小数点会以较小的形式显示在数字之间此时小数点不单独占用一个数字位当参数为false时小数点会按照正常大小显示并且会占用一个数字位。例如当显示12.34时如果小数点占用一个显示位那么整体显示结构可以理解为1 2 . 3 4此时一共需要 5 个显示位置。ui-lcdNumber-setDigitCount(5);ui-lcdNumber-setSmallDecimalPoint(false);ui-lcdNumber-display(12.34);如果将digitCount设置为 4并且小数点仍然占用一个显示位ui-lcdNumber-setDigitCount(4);ui-lcdNumber-setSmallDecimalPoint(false);ui-lcdNumber-display(12.34);此时显示容量就不够了因为12.34需要1、2、.、3、4共 5 个显示位置。而如果启用较小的小数点显示模式ui-lcdNumber-setSmallDecimalPoint(true);小数点就不会单独占用digitCount中的一个位置主要占用显示位的是1、2、3、4这几个数字。因此QLCDNumber中几个常用接口之间的关系可以这样理解display()用于设置当前显示的值setMode()用于控制数值按照什么进制显示setDigitCount()用于控制控件整体能够显示多少个数字位setSmallDecimalPoint()则用于控制小数点是否单独占用一个显示位。除了通过display()设置当前显示内容之外QLCDNumber也提供了用于获取当前显示值的接口。常用的读取接口主要有两个intValue()和value()。其中intValue()用于获取当前显示值对应的整数形式返回值类型为int而value()用于获取当前显示值对应的浮点形式返回值类型为double。ui-lcdNumber-display(3.14);intnui-lcdNumber-intValue();// 获取整数形式的显示值doubledui-lcdNumber-value();// 获取浮点形式的显示值需要注意的是虽然display()可以接收浮点数但如果后续通过intValue()获取当前显示值那么得到的是整数形式并不会保留小数部分。因此如果当前控件用于显示计数器、倒计时等整数场景可以使用intValue()获取当前值如果控件用于显示小数并且希望保留小数部分则应该使用value()接口。因此display()可以理解为负责“写入当前显示值”而intValue()和value()则负责“读取当前显示值”。其中intValue()侧重整数读取value()侧重浮点数读取。QLCDNumber 实战结合 QTimer 实现倒计时效果在认识了QLCDNumber的相关属性和常用接口之后接下来我们通过一个常见的应用场景来进一步理解它的使用方式这个应用场景就是倒计时。倒计时的核心逻辑并不复杂首先在界面中显示一个初始数值然后每隔一段固定时间对该数值进行更新直到数值减小到 0 为止。因此这里除了需要使用QLCDNumber显示当前倒计时数值之外还需要借助QTimer类来完成周期性触发任务。QTimer本质上是 Qt 提供的定时器类它可以按照指定的时间间隔周期性地发出timeout()信号。我们只需要将该信号和自定义槽函数进行连接就可以在槽函数中完成周期性任务例如更新QLCDNumber当前显示的数值。需要注意的是QTimer并不是显示类控件它不会直接显示在界面中。前面学习QLabel、QPushButton等控件时给控件传递父指针通常有两层含义一方面是应用 Qt 的父子对象机制让子对象的生命周期交给父对象管理另一方面是确定该控件显示在哪个父窗口区域中。但是对于QTimer来说它并不继承QWidget而是继承自QObject因此它不具备界面显示能力。创建QTimer对象时传入this主要是为了应用 Qt 的对象树机制timernewQTimer(this);这样一来timer就会成为当前Widget对象的子对象。当Widget被销毁时作为子对象的QTimer也会被自动销毁从而避免我们手动释放定时器对象。创建定时器对象之后可以通过start()设置定时器的触发间隔。start()接收的参数单位是毫秒例如timer-start(1000);表示定时器每隔1000ms也就是每隔 1 秒发出一次timeout()信号。接着通过connect()将timeout()信号和槽函数绑定起来connect(timer,QTimer::timeout,this,Widget::handler);这样每当定时器触发时都会自动调用handler()槽函数。在槽函数中我们可以先通过intValue()获取QLCDNumber当前显示的整数值然后判断倒计时是否已经结束。如果当前值已经小于等于 0就调用stop()停止定时器否则将当前值减 1并再次通过display()更新到界面中。完整代码如下#includewidget.h#includeui_widget.h#includeQTimerWidget::Widget(QWidget*parent):QWidget(parent),ui(newUi::Widget){ui-setupUi(this);// 设置 LCD 初始显示值ui-lcdNumber-display(10);// 创建定时器对象并将当前窗口作为父对象timernewQTimer(this);// 绑定 timeout 信号和自定义槽函数connect(timer,QTimer::timeout,this,Widget::handler);// 每隔 1000ms 触发一次 timeout 信号timer-start(1000);// 设置 LCD 控件样式ui-lcdNumber-setStyleSheet(QLCDNumber {color: green;background-color: black;border: 2px solid gray;});}Widget::~Widget(){deleteui;}voidWidget::handler(){intvalueui-lcdNumber-intValue();if(value0){timer-stop();return;}value--;ui-lcdNumber-display(value);}在这个案例中QLCDNumber负责显示当前倒计时数值而QTimer负责按照固定时间间隔触发更新逻辑。二者结合之后就可以实现一个简单的倒计时效果。QProgressBar 进度条控件范围设置、进度更新与定时器模拟根据上文我们已经认识了QLCDNumber这种 LCD 数字显示控件。接下来要学习的显示类控件是QProgressBar也就是进度条控件。QProgressBar主要用于在界面中展示某个任务的完成进度。它会根据当前值在指定区间中的位置计算出当前进度比例并以进度条长度的形式展示出来。简单来说进度条的显示效果取决于三个核心值最小值、最大值以及当前值。其中最小值和最大值用于确定整个进度范围当前值用于表示任务当前执行到了哪个位置。进度比例可以简单理解为当前进度比例 (当前值 - 最小值) / (最大值 - 最小值)因此当我们将进度条范围设置为0 ~ 100时当前值就可以直接理解为百分比。例如当前值为30就表示任务完成了30%当前值为100就表示任务已经完成。在代码中可以通过setMinimum()和setMaximum()分别设置进度条的最小值和最大值ui-progressBar-setMinimum(0);ui-progressBar-setMaximum(100);也可以使用setRange()一次性设置进度条的范围ui-progressBar-setRange(0,100);设置好范围之后可以通过setValue()设置当前进度值ui-progressBar-setValue(0);而如果需要获取当前进度条的值则可以调用value()接口intvalueui-progressBar-value();需要注意的是QProgressBar的当前值是整数类型因此它通常适合用来表示整数进度。例如在0 ~ 100的范围中可以将当前值直接理解为百分比而在文件读取、文件下载、文件传输等场景中也可以将进度条范围设置为0 ~ 文件总大小再根据当前已经读取或传输的字节数更新进度条。例如在文件读取场景中可以先获取文件总大小然后将进度条的最大值设置为文件总字节数。随着文件不断被读取再将已经读取的字节数设置为当前值这样进度条就可以根据真实读取进度进行变化。为了演示QProgressBar的基本使用方式我们可以先实现一个简单的模拟进度条案例。这里仍然需要借助QTimer定时器类。QTimer会按照指定时间间隔周期性地发出timeout()信号我们将该信号和槽函数绑定起来然后在槽函数中不断修改进度条的当前值就可以模拟一个自动增长的进度条效果。完整代码如下#includewidget.h#includeui_widget.h#includeQTimerWidget::Widget(QWidget*parent):QWidget(parent),ui(newUi::Widget){ui-setupUi(this);// 设置进度条范围ui-progressBar-setRange(0,100);// 设置进度条初始值ui-progressBar-setValue(0);// 创建定时器对象并将当前窗口作为父对象qtimernewQTimer(this);// 绑定 timeout 信号和自定义槽函数connect(qtimer,QTimer::timeout,this,Widget::handler);// 每隔 10ms 触发一次 timeout 信号qtimer-start(10);}Widget::~Widget(){deleteui;}voidWidget::handler(){intvalueui-progressBar-value();if(value100){qtimer-stop();return;}value;ui-progressBar-setValue(value);}在这段代码中首先将进度条的范围设置为0 ~ 100并将初始值设置为0。随后创建一个QTimer定时器对象并将它的timeout()信号连接到handler()槽函数。当定时器启动后它会每隔10ms触发一次timeout()信号从而调用一次handler()。在槽函数中我们先通过value()获取进度条当前的值如果当前值已经大于等于100说明进度条已经到达最大值此时调用stop()停止定时器否则将当前值加1再通过setValue()更新进度条显示。通过这个案例可以看到QProgressBar负责展示当前进度而QTimer负责周期性触发更新逻辑。二者结合之后就可以实现一个自动增长的进度条效果。QCalendarWidget 日历控件显示属性、日期范围与选择事件认识了进度条控件之后接下来我们继续学习另一个常用的显示类控件QCalendarWidget也就是日历控件。和前面学习的QLCDNumber、QProgressBar相比QCalendarWidget展示的内容结构要更加复杂。QLCDNumber主要用于展示数字QProgressBar主要用于展示进度比例而QCalendarWidget则会在界面中绘制出一个接近我们日常使用习惯的日历用于展示日期信息并支持用户选择具体日期。从界面结构上来看QCalendarWidget通常由上方的导航区域和下方的日期表格组成。上方导航区域用于显示当前年份和月份并提供月份切换功能下方日期表格则按照周和日期进行组织每一个单元格都对应一个具体日期。用户可以通过鼠标点击的方式在日历中选择日期。对于QCalendarWidget来说Qt 也提供了一系列接口用于控制日历的显示效果。首先可以通过setGridVisible()设置日历表格是否显示网格线ui-calendarWidget-setGridVisible(true);当参数为true时日历中的日期单元格之间会显示网格线当参数为false时则不会显示网格线。不显示网格线显示网格线其次可以通过setHorizontalHeaderFormat()设置日历控件横向表头的显示格式。这里的横向表头指的是日历日期区域上方用于显示星期名称的一行。例如在日历表格中日期区域上方通常会显示“星期一、星期二、星期三……”或者对应的缩写形式这一行就是横向表头。ui-calendarWidget-setHorizontalHeaderFormat(QCalendarWidget::ShortDayNames);QCalendarWidget::ShortDayNames表示使用较短的星期名称进行显示。例如在英文环境下完整星期名称可能是Monday、Tuesday、Wednesday而较短名称则可能显示为Mon、Tue、Wed。也就是说ShortDayNames会使用星期名称的缩写形式避免表头内容过长。除了ShortDayNames之外QCalendarWidget还提供了其他几种横向表头显示方式ui-calendarWidget-setHorizontalHeaderFormat(QCalendarWidget::LongDayNames);ui-calendarWidget-setHorizontalHeaderFormat(QCalendarWidget::ShortDayNames);ui-calendarWidget-setHorizontalHeaderFormat(QCalendarWidget::SingleLetterDayNames);ui-calendarWidget-setHorizontalHeaderFormat(QCalendarWidget::NoHorizontalHeader);其中LongDayNames表示显示完整的星期名称例如MondayShortDayNames表示显示较短的星期缩写例如MonSingleLetterDayNames表示只显示单字母形式例如M而NoHorizontalHeader则表示隐藏横向星期表头。如果处于中文环境下实际显示内容可能会受到系统语言环境和 Qt 本地化配置的影响。例如完整名称可能显示为“星期一”较短名称可能显示为“周一”或者“一”。因此在理解这个接口时不需要死记具体显示成什么文字只需要抓住它的核心作用setHorizontalHeaderFormat()用于控制日历上方“星期表头”的显示形式。除了横向表头之外QCalendarWidget还可以通过setVerticalHeaderFormat()设置纵向表头的显示格式。这里需要注意纵向表头并不是日历顶部显示年份和月份的区域。顶部显示当前年份、月份并且可以切换上一个月或下一个月的区域更准确地说应该叫导航栏或导航区域。而纵向表头指的是日历日期表格最左侧的一列。横向表头通常位于日期表格上方用于显示一周中的星期名称例如“周一、周二、周三……”而纵向表头则位于日期表格左侧通常用于显示当前这一行日期属于一年中的第几周。例如当设置为ui-calendarWidget-setVerticalHeaderFormat(QCalendarWidget::ISOWeekNumbers);此时日历表格最左侧会显示一列数字例如22、23、24等。这些数字表示对应这一行日期属于当前年份中的第几周也就是周编号。可以简单理解为周一 周二 周三 周四 周五 周六 周日 22 1 2 3 4 5 6 7 23 8 9 10 11 12 13 14 24 15 16 17 18 19 20 21其中左侧的22表示这一行日期所在的这一周是当前年份中的第 22 周下一行的23表示下一周是当前年份中的第 23 周。如果不希望显示这一列周编号也可以将纵向表头设置为隐藏ui-calendarWidget-setVerticalHeaderFormat(QCalendarWidget::NoVerticalHeader);因此QCalendarWidget中几个区域可以这样区分顶部显示年份和月份的区域是导航栏日期表格上方显示星期名称的一行是横向表头日期表格左侧显示周编号的一列是纵向表头。因此QCalendarWidget的基础显示属性可以先从三个方面理解setGridVisible()用于控制是否显示日期单元格之间的网格线setHorizontalHeaderFormat()用于控制横向星期表头的显示格式setVerticalHeaderFormat()用于控制纵向周编号表头的显示格式。通过这些接口我们可以对日历控件的基础显示效果进行定制使其更加符合实际界面需求。认识了QCalendarWidget的显示属性之后我们还可以继续设置日历控件的可选日期范围。这里所谓的范围并不是普通数值范围而是日期范围。可以通过setMinimumDate()设置最小可选日期通过setMaximumDate()设置最大可选日期ui-calendarWidget-setMinimumDate(QDate(2026,1,1));ui-calendarWidget-setMaximumDate(QDate(2026,12,31));也可以使用setDateRange()一次性设置最小日期和最大日期ui-calendarWidget-setDateRange(QDate(2026,1,1),QDate(2026,12,31));需要注意的是最小日期和最大日期限制的是“用户可以选中的日期范围”而不是简单地控制哪些日期会被绘制出来。由于QCalendarWidget通常以完整月份的形式进行展示为了保证日历表格结构完整超出范围的日期仍然可能会显示在界面中。不过这些超出范围的日期通常会以灰色或禁用状态显示表示它们不可选中。用户点击这些日期时日历控件不会将其设置为当前选中日期因此也不会触发正常的日期选择逻辑。也就是说日期范围限制影响的是日期的“可选性”而不是一定影响日期是否出现在界面中。除了设置可选日期范围之外QCalendarWidget还提供了日期选择相关的交互机制。当用户在日历中选中的日期发生变化时控件会发出selectionChanged()信号。我们可以将该信号连接到自定义槽函数然后在槽函数中获取当前选中的日期并将其显示到标签控件中。connect(ui-calendarWidget,QCalendarWidget::selectionChanged,this,Widget::handler);在槽函数中可以通过selectedDate()获取当前选中的日期。该接口返回的是一个QDate类型的对象QDate dateui-calendarWidget-selectedDate();如果希望将这个日期显示到QLabel中就需要先将QDate转换成字符串。这里可以调用QDate的toString()接口并通过格式化字符串控制日期的显示格式ui-label-setText(date.toString(yyyy年MM月dd日));其中yyyy表示四位年份MM表示两位月份dd表示两位日期。需要注意的是日期格式化字符串对大小写和重复次数有要求。例如月份应该使用大写的MM日期应该使用小写的dd。如果格式写错就可能无法得到预期的显示结果。当然toString()也可以不传递格式化字符串。此时 Qt 会按照默认格式将日期转换成字符串。不过在实际界面开发中为了让显示效果更加明确通常会主动指定日期格式。完整代码如下#includewidget.h#includeui_widget.h#includeQDateWidget::Widget(QWidget*parent):QWidget(parent),ui(newUi::Widget){ui-setupUi(this);// 设置日历基础显示属性ui-calendarWidget-setGridVisible(true);ui-calendarWidget-setHorizontalHeaderFormat(QCalendarWidget::ShortDayNames);ui-calendarWidget-setVerticalHeaderFormat(QCalendarWidget::ISOWeekNumbers);// 设置日期可选范围ui-calendarWidget-setMinimumDate(QDate(2026,1,1));ui-calendarWidget-setMaximumDate(QDate(2026,12,31));// 初始化标签内容默认显示当前系统日期ui-label-setText(QDate::currentDate().toString(yyyy年MM月dd日));// 当选中日期发生变化时更新标签内容connect(ui-calendarWidget,QCalendarWidget::selectionChanged,this,Widget::handler);}Widget::~Widget(){deleteui;}voidWidget::handler(){QDate dateui-calendarWidget-selectedDate();ui-label-setText(date.toString(yyyy年MM月dd日));}在这段代码中QDate::currentDate()用于获取系统当前日期并在程序启动时初始化标签内容而selectedDate()用于获取用户在日历控件中当前选中的日期。每当用户选择的日期发生变化时selectionChanged()信号都会触发槽函数从而更新标签中显示的日期信息。结语那么这就是本篇文章的全部内容我会持续更新希望你能够多多关注如果本文有帮助到你的话还请三连加关注你的支持就是我创作的最大动力
【Qt入门系列】一文掌握 Qt 常用显示类控件:QLCDNumber、QProgressBar 与 QCalendarWidget
发布时间:2026/6/6 2:30:11
本文专栏Qt作者主页努力努力再努力wz今日博客励志语录别怕慢怕的是你一边走一边怀疑这条路结果连慢都没攒下来。思维导图引入在此前的学习中我们已经了解了 Qt 中的一些常用控件包括按钮类控件和标签类控件。通过这些内容我们初步认识了 Qt 控件的基本使用方式以及控件在界面显示、用户交互和信号槽机制中的作用。本文将继续围绕 Qt 常用控件展开进一步学习其他典型控件的使用方式并结合实际代码分析其常见属性、信号槽连接方式以及在界面开发中的应用场景。QLCDNumber 数字显示控件从基础显示控制到倒计时案例QLCDNumberLCD 数字显示控件的基本使用与显示控制首先要介绍的显示类控件是QLCDNumber即LCD 数字显示控件。从功能定位上来看QLCDNumber和前面学习过的QLabel有一定相似之处它们都可以在界面中展示内容。不过二者的侧重点并不相同QLabel更偏向通用文本或图片展示可以显示普通字符串、富文本以及图片而QLCDNumber则更侧重于数值展示它会以类似电子表、计算器或数码管的 LCD 风格显示数字。在实际开发中QLCDNumber的外观属性既可以在 Qt Designer 中通过可视化方式进行设置也可以通过 C 代码进行控制。例如可以设置它的数字位数、显示模式、小数点样式等属性。对于QLCDNumber来说设置当前显示内容的核心接口是display()。该接口提供了多个重载版本既可以接收整数也可以接收浮点数还可以接收字符串形式的内容并将其以 LCD 数字风格显示到界面中。ui-lcdNumber-display(10);// 显示整数ui-lcdNumber-display(3.14);// 显示浮点数ui-lcdNumber-display(12:30);// 显示部分 LCD 风格支持的字符串需要注意的是虽然display()可以接收字符串参数但QLCDNumber并不是通用字符串显示控件。由于它采用 LCD 数码管风格进行绘制因此只能显示数字以及少量适合数码管表示的字符例如负号、小数点、冒号、部分英文字母等。如果传入了不支持的字符这些字符会被替换为空格。因此如果只是普通文本展示更适合使用QLabel如果是数字、时间、计数器、倒计时等内容展示则更适合使用QLCDNumber。除了设置显示值之外QLCDNumber还可以控制数值的显示进制。它支持十进制、十六进制、八进制和二进制显示模式ui-lcdNumber-setMode(QLCDNumber::Dec);// 十进制ui-lcdNumber-setMode(QLCDNumber::Hex);// 十六进制ui-lcdNumber-setMode(QLCDNumber::Oct);// 八进制ui-lcdNumber-setMode(QLCDNumber::Bin);// 二进制也可以使用对应的槽函数来切换显示模式ui-lcdNumber-setDecMode();ui-lcdNumber-setHexMode();ui-lcdNumber-setOctMode();ui-lcdNumber-setBinMode();需要注意的是QLCDNumber虽然可以通过display(double)接收浮点数但只有在十进制模式下才会正常显示小数部分。当控件处于十六进制、八进制或二进制模式时传入浮点数本身不会导致接口调用错误但控件会按照该数值对应的整数形式进行进制显示因此不会展示小数部分。对于显示位数QLCDNumber提供了setDigitCount()接口。该接口用于设置控件当前能够显示的数字位数例如ui-lcdNumber-setDigitCount(5);这里的5表示控件最多显示 5 个数字位而不是表示小数点后保留 5 位。如果传入display()的内容超出了当前digitCount所能容纳的范围控件就无法完整显示该内容并可能触发overflow()信号。例如ui-lcdNumber-setDigitCount(5);ui-lcdNumber-display(12345);// 可以完整显示ui-lcdNumber-display(123456);// 超出 5 位可能触发 overflow()如果显示的是小数还需要结合setSmallDecimalPoint()来理解。该接口用于控制小数点的显示方式ui-lcdNumber-setSmallDecimalPoint(true);当参数为true时小数点会以较小的形式显示在数字之间此时小数点不单独占用一个数字位当参数为false时小数点会按照正常大小显示并且会占用一个数字位。例如当显示12.34时如果小数点占用一个显示位那么整体显示结构可以理解为1 2 . 3 4此时一共需要 5 个显示位置。ui-lcdNumber-setDigitCount(5);ui-lcdNumber-setSmallDecimalPoint(false);ui-lcdNumber-display(12.34);如果将digitCount设置为 4并且小数点仍然占用一个显示位ui-lcdNumber-setDigitCount(4);ui-lcdNumber-setSmallDecimalPoint(false);ui-lcdNumber-display(12.34);此时显示容量就不够了因为12.34需要1、2、.、3、4共 5 个显示位置。而如果启用较小的小数点显示模式ui-lcdNumber-setSmallDecimalPoint(true);小数点就不会单独占用digitCount中的一个位置主要占用显示位的是1、2、3、4这几个数字。因此QLCDNumber中几个常用接口之间的关系可以这样理解display()用于设置当前显示的值setMode()用于控制数值按照什么进制显示setDigitCount()用于控制控件整体能够显示多少个数字位setSmallDecimalPoint()则用于控制小数点是否单独占用一个显示位。除了通过display()设置当前显示内容之外QLCDNumber也提供了用于获取当前显示值的接口。常用的读取接口主要有两个intValue()和value()。其中intValue()用于获取当前显示值对应的整数形式返回值类型为int而value()用于获取当前显示值对应的浮点形式返回值类型为double。ui-lcdNumber-display(3.14);intnui-lcdNumber-intValue();// 获取整数形式的显示值doubledui-lcdNumber-value();// 获取浮点形式的显示值需要注意的是虽然display()可以接收浮点数但如果后续通过intValue()获取当前显示值那么得到的是整数形式并不会保留小数部分。因此如果当前控件用于显示计数器、倒计时等整数场景可以使用intValue()获取当前值如果控件用于显示小数并且希望保留小数部分则应该使用value()接口。因此display()可以理解为负责“写入当前显示值”而intValue()和value()则负责“读取当前显示值”。其中intValue()侧重整数读取value()侧重浮点数读取。QLCDNumber 实战结合 QTimer 实现倒计时效果在认识了QLCDNumber的相关属性和常用接口之后接下来我们通过一个常见的应用场景来进一步理解它的使用方式这个应用场景就是倒计时。倒计时的核心逻辑并不复杂首先在界面中显示一个初始数值然后每隔一段固定时间对该数值进行更新直到数值减小到 0 为止。因此这里除了需要使用QLCDNumber显示当前倒计时数值之外还需要借助QTimer类来完成周期性触发任务。QTimer本质上是 Qt 提供的定时器类它可以按照指定的时间间隔周期性地发出timeout()信号。我们只需要将该信号和自定义槽函数进行连接就可以在槽函数中完成周期性任务例如更新QLCDNumber当前显示的数值。需要注意的是QTimer并不是显示类控件它不会直接显示在界面中。前面学习QLabel、QPushButton等控件时给控件传递父指针通常有两层含义一方面是应用 Qt 的父子对象机制让子对象的生命周期交给父对象管理另一方面是确定该控件显示在哪个父窗口区域中。但是对于QTimer来说它并不继承QWidget而是继承自QObject因此它不具备界面显示能力。创建QTimer对象时传入this主要是为了应用 Qt 的对象树机制timernewQTimer(this);这样一来timer就会成为当前Widget对象的子对象。当Widget被销毁时作为子对象的QTimer也会被自动销毁从而避免我们手动释放定时器对象。创建定时器对象之后可以通过start()设置定时器的触发间隔。start()接收的参数单位是毫秒例如timer-start(1000);表示定时器每隔1000ms也就是每隔 1 秒发出一次timeout()信号。接着通过connect()将timeout()信号和槽函数绑定起来connect(timer,QTimer::timeout,this,Widget::handler);这样每当定时器触发时都会自动调用handler()槽函数。在槽函数中我们可以先通过intValue()获取QLCDNumber当前显示的整数值然后判断倒计时是否已经结束。如果当前值已经小于等于 0就调用stop()停止定时器否则将当前值减 1并再次通过display()更新到界面中。完整代码如下#includewidget.h#includeui_widget.h#includeQTimerWidget::Widget(QWidget*parent):QWidget(parent),ui(newUi::Widget){ui-setupUi(this);// 设置 LCD 初始显示值ui-lcdNumber-display(10);// 创建定时器对象并将当前窗口作为父对象timernewQTimer(this);// 绑定 timeout 信号和自定义槽函数connect(timer,QTimer::timeout,this,Widget::handler);// 每隔 1000ms 触发一次 timeout 信号timer-start(1000);// 设置 LCD 控件样式ui-lcdNumber-setStyleSheet(QLCDNumber {color: green;background-color: black;border: 2px solid gray;});}Widget::~Widget(){deleteui;}voidWidget::handler(){intvalueui-lcdNumber-intValue();if(value0){timer-stop();return;}value--;ui-lcdNumber-display(value);}在这个案例中QLCDNumber负责显示当前倒计时数值而QTimer负责按照固定时间间隔触发更新逻辑。二者结合之后就可以实现一个简单的倒计时效果。QProgressBar 进度条控件范围设置、进度更新与定时器模拟根据上文我们已经认识了QLCDNumber这种 LCD 数字显示控件。接下来要学习的显示类控件是QProgressBar也就是进度条控件。QProgressBar主要用于在界面中展示某个任务的完成进度。它会根据当前值在指定区间中的位置计算出当前进度比例并以进度条长度的形式展示出来。简单来说进度条的显示效果取决于三个核心值最小值、最大值以及当前值。其中最小值和最大值用于确定整个进度范围当前值用于表示任务当前执行到了哪个位置。进度比例可以简单理解为当前进度比例 (当前值 - 最小值) / (最大值 - 最小值)因此当我们将进度条范围设置为0 ~ 100时当前值就可以直接理解为百分比。例如当前值为30就表示任务完成了30%当前值为100就表示任务已经完成。在代码中可以通过setMinimum()和setMaximum()分别设置进度条的最小值和最大值ui-progressBar-setMinimum(0);ui-progressBar-setMaximum(100);也可以使用setRange()一次性设置进度条的范围ui-progressBar-setRange(0,100);设置好范围之后可以通过setValue()设置当前进度值ui-progressBar-setValue(0);而如果需要获取当前进度条的值则可以调用value()接口intvalueui-progressBar-value();需要注意的是QProgressBar的当前值是整数类型因此它通常适合用来表示整数进度。例如在0 ~ 100的范围中可以将当前值直接理解为百分比而在文件读取、文件下载、文件传输等场景中也可以将进度条范围设置为0 ~ 文件总大小再根据当前已经读取或传输的字节数更新进度条。例如在文件读取场景中可以先获取文件总大小然后将进度条的最大值设置为文件总字节数。随着文件不断被读取再将已经读取的字节数设置为当前值这样进度条就可以根据真实读取进度进行变化。为了演示QProgressBar的基本使用方式我们可以先实现一个简单的模拟进度条案例。这里仍然需要借助QTimer定时器类。QTimer会按照指定时间间隔周期性地发出timeout()信号我们将该信号和槽函数绑定起来然后在槽函数中不断修改进度条的当前值就可以模拟一个自动增长的进度条效果。完整代码如下#includewidget.h#includeui_widget.h#includeQTimerWidget::Widget(QWidget*parent):QWidget(parent),ui(newUi::Widget){ui-setupUi(this);// 设置进度条范围ui-progressBar-setRange(0,100);// 设置进度条初始值ui-progressBar-setValue(0);// 创建定时器对象并将当前窗口作为父对象qtimernewQTimer(this);// 绑定 timeout 信号和自定义槽函数connect(qtimer,QTimer::timeout,this,Widget::handler);// 每隔 10ms 触发一次 timeout 信号qtimer-start(10);}Widget::~Widget(){deleteui;}voidWidget::handler(){intvalueui-progressBar-value();if(value100){qtimer-stop();return;}value;ui-progressBar-setValue(value);}在这段代码中首先将进度条的范围设置为0 ~ 100并将初始值设置为0。随后创建一个QTimer定时器对象并将它的timeout()信号连接到handler()槽函数。当定时器启动后它会每隔10ms触发一次timeout()信号从而调用一次handler()。在槽函数中我们先通过value()获取进度条当前的值如果当前值已经大于等于100说明进度条已经到达最大值此时调用stop()停止定时器否则将当前值加1再通过setValue()更新进度条显示。通过这个案例可以看到QProgressBar负责展示当前进度而QTimer负责周期性触发更新逻辑。二者结合之后就可以实现一个自动增长的进度条效果。QCalendarWidget 日历控件显示属性、日期范围与选择事件认识了进度条控件之后接下来我们继续学习另一个常用的显示类控件QCalendarWidget也就是日历控件。和前面学习的QLCDNumber、QProgressBar相比QCalendarWidget展示的内容结构要更加复杂。QLCDNumber主要用于展示数字QProgressBar主要用于展示进度比例而QCalendarWidget则会在界面中绘制出一个接近我们日常使用习惯的日历用于展示日期信息并支持用户选择具体日期。从界面结构上来看QCalendarWidget通常由上方的导航区域和下方的日期表格组成。上方导航区域用于显示当前年份和月份并提供月份切换功能下方日期表格则按照周和日期进行组织每一个单元格都对应一个具体日期。用户可以通过鼠标点击的方式在日历中选择日期。对于QCalendarWidget来说Qt 也提供了一系列接口用于控制日历的显示效果。首先可以通过setGridVisible()设置日历表格是否显示网格线ui-calendarWidget-setGridVisible(true);当参数为true时日历中的日期单元格之间会显示网格线当参数为false时则不会显示网格线。不显示网格线显示网格线其次可以通过setHorizontalHeaderFormat()设置日历控件横向表头的显示格式。这里的横向表头指的是日历日期区域上方用于显示星期名称的一行。例如在日历表格中日期区域上方通常会显示“星期一、星期二、星期三……”或者对应的缩写形式这一行就是横向表头。ui-calendarWidget-setHorizontalHeaderFormat(QCalendarWidget::ShortDayNames);QCalendarWidget::ShortDayNames表示使用较短的星期名称进行显示。例如在英文环境下完整星期名称可能是Monday、Tuesday、Wednesday而较短名称则可能显示为Mon、Tue、Wed。也就是说ShortDayNames会使用星期名称的缩写形式避免表头内容过长。除了ShortDayNames之外QCalendarWidget还提供了其他几种横向表头显示方式ui-calendarWidget-setHorizontalHeaderFormat(QCalendarWidget::LongDayNames);ui-calendarWidget-setHorizontalHeaderFormat(QCalendarWidget::ShortDayNames);ui-calendarWidget-setHorizontalHeaderFormat(QCalendarWidget::SingleLetterDayNames);ui-calendarWidget-setHorizontalHeaderFormat(QCalendarWidget::NoHorizontalHeader);其中LongDayNames表示显示完整的星期名称例如MondayShortDayNames表示显示较短的星期缩写例如MonSingleLetterDayNames表示只显示单字母形式例如M而NoHorizontalHeader则表示隐藏横向星期表头。如果处于中文环境下实际显示内容可能会受到系统语言环境和 Qt 本地化配置的影响。例如完整名称可能显示为“星期一”较短名称可能显示为“周一”或者“一”。因此在理解这个接口时不需要死记具体显示成什么文字只需要抓住它的核心作用setHorizontalHeaderFormat()用于控制日历上方“星期表头”的显示形式。除了横向表头之外QCalendarWidget还可以通过setVerticalHeaderFormat()设置纵向表头的显示格式。这里需要注意纵向表头并不是日历顶部显示年份和月份的区域。顶部显示当前年份、月份并且可以切换上一个月或下一个月的区域更准确地说应该叫导航栏或导航区域。而纵向表头指的是日历日期表格最左侧的一列。横向表头通常位于日期表格上方用于显示一周中的星期名称例如“周一、周二、周三……”而纵向表头则位于日期表格左侧通常用于显示当前这一行日期属于一年中的第几周。例如当设置为ui-calendarWidget-setVerticalHeaderFormat(QCalendarWidget::ISOWeekNumbers);此时日历表格最左侧会显示一列数字例如22、23、24等。这些数字表示对应这一行日期属于当前年份中的第几周也就是周编号。可以简单理解为周一 周二 周三 周四 周五 周六 周日 22 1 2 3 4 5 6 7 23 8 9 10 11 12 13 14 24 15 16 17 18 19 20 21其中左侧的22表示这一行日期所在的这一周是当前年份中的第 22 周下一行的23表示下一周是当前年份中的第 23 周。如果不希望显示这一列周编号也可以将纵向表头设置为隐藏ui-calendarWidget-setVerticalHeaderFormat(QCalendarWidget::NoVerticalHeader);因此QCalendarWidget中几个区域可以这样区分顶部显示年份和月份的区域是导航栏日期表格上方显示星期名称的一行是横向表头日期表格左侧显示周编号的一列是纵向表头。因此QCalendarWidget的基础显示属性可以先从三个方面理解setGridVisible()用于控制是否显示日期单元格之间的网格线setHorizontalHeaderFormat()用于控制横向星期表头的显示格式setVerticalHeaderFormat()用于控制纵向周编号表头的显示格式。通过这些接口我们可以对日历控件的基础显示效果进行定制使其更加符合实际界面需求。认识了QCalendarWidget的显示属性之后我们还可以继续设置日历控件的可选日期范围。这里所谓的范围并不是普通数值范围而是日期范围。可以通过setMinimumDate()设置最小可选日期通过setMaximumDate()设置最大可选日期ui-calendarWidget-setMinimumDate(QDate(2026,1,1));ui-calendarWidget-setMaximumDate(QDate(2026,12,31));也可以使用setDateRange()一次性设置最小日期和最大日期ui-calendarWidget-setDateRange(QDate(2026,1,1),QDate(2026,12,31));需要注意的是最小日期和最大日期限制的是“用户可以选中的日期范围”而不是简单地控制哪些日期会被绘制出来。由于QCalendarWidget通常以完整月份的形式进行展示为了保证日历表格结构完整超出范围的日期仍然可能会显示在界面中。不过这些超出范围的日期通常会以灰色或禁用状态显示表示它们不可选中。用户点击这些日期时日历控件不会将其设置为当前选中日期因此也不会触发正常的日期选择逻辑。也就是说日期范围限制影响的是日期的“可选性”而不是一定影响日期是否出现在界面中。除了设置可选日期范围之外QCalendarWidget还提供了日期选择相关的交互机制。当用户在日历中选中的日期发生变化时控件会发出selectionChanged()信号。我们可以将该信号连接到自定义槽函数然后在槽函数中获取当前选中的日期并将其显示到标签控件中。connect(ui-calendarWidget,QCalendarWidget::selectionChanged,this,Widget::handler);在槽函数中可以通过selectedDate()获取当前选中的日期。该接口返回的是一个QDate类型的对象QDate dateui-calendarWidget-selectedDate();如果希望将这个日期显示到QLabel中就需要先将QDate转换成字符串。这里可以调用QDate的toString()接口并通过格式化字符串控制日期的显示格式ui-label-setText(date.toString(yyyy年MM月dd日));其中yyyy表示四位年份MM表示两位月份dd表示两位日期。需要注意的是日期格式化字符串对大小写和重复次数有要求。例如月份应该使用大写的MM日期应该使用小写的dd。如果格式写错就可能无法得到预期的显示结果。当然toString()也可以不传递格式化字符串。此时 Qt 会按照默认格式将日期转换成字符串。不过在实际界面开发中为了让显示效果更加明确通常会主动指定日期格式。完整代码如下#includewidget.h#includeui_widget.h#includeQDateWidget::Widget(QWidget*parent):QWidget(parent),ui(newUi::Widget){ui-setupUi(this);// 设置日历基础显示属性ui-calendarWidget-setGridVisible(true);ui-calendarWidget-setHorizontalHeaderFormat(QCalendarWidget::ShortDayNames);ui-calendarWidget-setVerticalHeaderFormat(QCalendarWidget::ISOWeekNumbers);// 设置日期可选范围ui-calendarWidget-setMinimumDate(QDate(2026,1,1));ui-calendarWidget-setMaximumDate(QDate(2026,12,31));// 初始化标签内容默认显示当前系统日期ui-label-setText(QDate::currentDate().toString(yyyy年MM月dd日));// 当选中日期发生变化时更新标签内容connect(ui-calendarWidget,QCalendarWidget::selectionChanged,this,Widget::handler);}Widget::~Widget(){deleteui;}voidWidget::handler(){QDate dateui-calendarWidget-selectedDate();ui-label-setText(date.toString(yyyy年MM月dd日));}在这段代码中QDate::currentDate()用于获取系统当前日期并在程序启动时初始化标签内容而selectedDate()用于获取用户在日历控件中当前选中的日期。每当用户选择的日期发生变化时selectionChanged()信号都会触发槽函数从而更新标签中显示的日期信息。结语那么这就是本篇文章的全部内容我会持续更新希望你能够多多关注如果本文有帮助到你的话还请三连加关注你的支持就是我创作的最大动力