目录
[代码示例: 倒计时](#代码示例: 倒计时)
QLCDNumer 是一个专门用来显示数字的控件.类似于"老式计算器"的效果
核心属性
|-------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 属性 | 说明 |
| intValue | QLCDNumber显示的数字值(int). |
| value | QLCDNumber 显示的数字值(double). 和intValue是联动的. 例如给value设为1.5, intValue的值就是2. 另外,设苣value和intValue的方法名字为display,而不是setvalue或 者 setlntValue . |
| digitCount | 显示几位数字. |
| mode | 数字显示形式. 1. QLCDNumber::Dec :十进制模式,显示當规的十进制数字。 2. QLCDNumber::Hex :十六进制模式,以十六进制格式显示数字。 3. QLCDNumber::Bin :二进制模式,□二进制格式显示数字。 4. QLCDNumber: :Oct :八进制模式,汉八进制格式显示数字。 |只有十进制的时候才能显示小数点后旳内容. |
| segmentstyle | 设置显示风格. 1. QLCDNumber:: Flat:平面的显示风格,数字呈现在一个平坦的表面上。 2. QLCDNumber::Qutline :轮廓显示风格,数字具有清晰的轮廊和阴影效果果。 3. QLCDNumber:: Filled :填充显示风格,数字被填充颜色并与背景区分开。 |
| smallDecimalPoint | 设置比较小的小数点. |
代码示例: 倒计时
1)在界面上创建一个 QLCDNumber,初始值设为 10.
objectName 为 lcdNumber
2)修改 widget.h 代码,创建一个 QTimer
成员,和一个 updateTime 函数
3)修改 widget.cpp,在构造函数中初始化 QTimer
QTimer 表示定时器.通过 start 方法启动定时器之后,就会每隔一定周期,触发一次
QTimer::timeout 信号.
使用 connect 把 QTimer::timeout 信号和 Widget::updateTime 连接起来,意味着每
次触发 QTimer::timeout 都会执行 Widget::updateTime
4)修改 widget.cpp,实现 updateTime
通过 intValue 获取到 QLCDNumber 内部的数值
如果 value 的值归0了,就停止 QTimer,接下来 QTimer 也就不会触发 timeout信号了
报错,因为timer是局部变量,将它定义为类的成员变量,其他成员函数能够访问
5)执行程序,可以看到每隔一秒钟,显示的数字就减少 1.
倒计时.
使用 QLCDNumber 显示一个初始的数值,比如 10.
每隔一秒钟,数字就 -1
一直到 0,就停止了此处关键要点是要实现"每秒钟 -1"这个效果
周期性的执行某个逻辑~~
周期性实现某个逻辑功能会封装成类定时器"
C++ 标准库中,没有提供定时器的实现,Boost 里面提供了对应的功能
Qt 中也封装了对应的定时器~~(结合了信号槽机制的)QTimer
通过这个类创建出来的对象,就会产生一个 timeout 这样的信号~~
可以通过 start 方法来开启定时器,并且参数中设定触发 timeout 信号的
周期
结合 connect,把这个 timeout 信号绑定到需要的槽函数中,就可以执行逻辑,修改 LCDNumber 中的数字了.
针对上述代码存在两个问题
1)上述代码如果直接在 Widget 构造函数中通过一个循环 +sleep 的方式是否可以呢?
代码形如
显然,这个代码是不行的.循环会使 Widget 的构造函数无法执行完毕,此时界面是不能正确构造和显示的
sleep=> Windows 的 api,需要包含"Windows.h"头文件才能使用的~~
C++ 11 标准库中引入了 sleep 操作.
标准库就可以通过一些"条件编译"的方式来兼容不同的系统
sleep for
Widget 的构造函数
需要把 Widget 构造完毕, 然后才能执行后续的显示操作~~
会停顿10s才出现窗口
2)上述代码如果是在 Widget 构造函数中,另起一个线程,在新线程中完成 循环 + sleep 是否可以呢?
代码形如
这个代码同样是不行的.Qt 中规定,任何对于 GUI上内容的操作,必须在 主线程中完成像 Widget 构造函数,以及 connect 连接的 slot 函数,都是在主线程中调用的而我们自己创建的线程则不是
当我们自己的线程中尝试对界面元素进行修改时,Qt 程序往往会直接崩溃
这样的约定主要是因为 GUI中的状态往往是牵一发动全身的,修改一个地方,就需要同步的对
其他内容进行调整
比如调整了某个元素的尺寸,就可能影响到内部的文字位置,或者其他元素的位置.这里一连串
的修改,都是需要按照一定的顺序来完成的
由于多线程执行的顺序无法保障,因此 Qt 从根本上禁止了其他线程修改 GUI状态避免后续的
一系列问题,
terminate called without an active exceptionQt 里,界面有一个专门的线程去负责维护更新的(主线程)
(main 函数所在的线程)
对于 GUI 来说,内部包含了很多的隐状态,Qt 为了保证修改界面的过程中,线程安全是不会受到影响的,Qt 禁止了其他线程直接改界面
ui->lcdNumber>display(value);
形如这种操作,就是在修改界面~~
因此 Qt 为了确保线程安全,直接要求所有的对界面的修改操作,必须在主线程中完成!!对于 Qt 的槽函数来说,默认情况下,槽函数都是由主线程调用的
在槽函数中修改界面是没有任何问题的!!return a.exec();
a.exec 就会使主线程进入"事件循环
exec 就会一直循环下去,每执行一次循环,都会有一些固定的事情要操作~~
综上所述,使用定时器是实现上述功能的最合理方案
后续如果我们也有类似的需要"周期性修改界面状态"的需求,也需要优先考虑使用定时器