【Qt 常用控件】显示类控件2(QLCDNumber、QProgressBar、QCalenderWidget)
目录
1.QLCDNumber
例:实现倒计时
1.使用Qt定时器、结合信号槽
2.用循环,休眠函数
segmentStyle 数字显示风格
2.QProgressBar 进度条
例:按时间增长的进度条、每隔1000ms,让进度条的数值+1,直到100.
前置声明
例:写一个红色的进度条、使用样式表
3. QCalendarWidget 日历
例:获取选中日期,为selectionChanged(const QDate&)添加槽函数
1.QLCDNumber
- 功能:用于显示LCD风格的数字。
- 属性:
intValue | 显示的数字值(显示int类型) |
value | 显示的数字值(显示double类型) 设置方法:display,不是setValue和setIntValue。 intvalue和value设置一种,另一个会被同步设置。 设置小数,对应整数的取整方式是:四舍五入 |
digitCount | 显示数字的总位数 |
mode | 数字显示的形式、即显示几进制数字。 QLCDNumber::Dec:10进制 QLCDNumber::Hex:16进制 QLCDNumber::Bin:2进制 QLCDNumber::Oct:8进制 只有十进制数,才能显示小数点后的数字。 |
segmentStyle | 设置显示风格。 QLCDNumber::Flat:平面显示风格 QLCDNumber::OutLine:轮廓显示风格 QLCDNumber::Filled:填充显示风格 |
smallDecimalPoint | 是否显示小数点 |
例:实现倒计时
窗口启动显示倒计时起始秒数,数字一秒减小一次。
1.使用Qt定时器、结合信号槽
QTimer,.start启动定时器,同时设置定时器周期。.stop停止定时器 。
QTimer内部有一个信号,timeout,每次定时器设置的时间到达,都会触发一次timeout信号。
对timeout信号关联一个自定义的槽函数,在槽函数内部对lcdnuber的值进行-1操作。
#include "widget.h"
#include "ui_widget.h"
#include<QTimer>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//设置初始值
ui->lcdNumber->display(10);
//每秒钟数字-1
timer=new QTimer(this);
//关联定时器的timeout信号和自定义的槽函数
connect(timer,&QTimer::timeout,this,&Widget::handel);
timer->start(1000);//启动定时器,并设置定时器触发间隔,1秒
}
Widget::~Widget()
{
delete ui;
}
void Widget::handel()
{
//数字减小1
int val=ui->lcdNumber->intValue();
if(val<=0)
{
//停止定时器
timer->stop();
return ;
}
ui->lcdNumber->display(val-1);
}
2.用循环,休眠函数
1.sleep(linux系统调用接口),unistd.h。
2.Sleep(Windows系统调用接口),Windows.h。该接口在msvc编译器可用。
而Qt采用gcc编译器的windows版本,无法使用Windows.h。
C++11标准库引入的休眠接口,sleep_for,头文件<thread>
- 尝试1:在构造函数中
失败:原因在于程序启动在main函数中定义Widget对象,构造函数结束后,才显示控件。
所以,效果为:窗口在10秒之后才显示,且值为0。
- 尝试2:在构造函数中定义一个子线程,在子线程内部实现
失败原因:Qt为了保证线程安全,界面修改操作必须在主线程中完成,而禁止其他线程内对界面进行修改。
- 程序运行之后,为什么槽函数还可以被调用,允许对界面进行修改?
槽函数,一般也是由main函数所在线程(主线程)调用的,在槽函数中修改界面是可行的。
main函数中的return a.exec();//会使主线程进入事件循环,exec会一直循环,每一次都进行特定的操作。槽函数就会在这个时候被执行。
- 线程操作接口,也属于系统调用接口,推荐使用c++封装的线程接口,在内部通过条件编译的方式,实现跨平台代码。
- 后续如果我们也有类似的需要"周期性修改界⾯状态"的需求,也需要优先考虑使⽤定时器。
segmentStyle 数字显示风格
outline:
filled:
flat:
2.QProgressBar 进度条
- 功能:进度条
- 属性:
mininum | 进度条的最小值 |
maxinum | 进度条的最大值 |
value | 进度条的当前值 |
alignment | 文本在进度条控件中的对齐方式 Qt::AlignLeft:左对齐 Qt::ALignRight:右对齐 Qt::AlignCenter:居中对齐(水平+垂直居中) Qt::AlignJustify:两端对齐 |
textVisible | 进度条数字是否可见 |
orientation | 进度条方向:水平、垂直 |
invertAppearance | 进度条是否朝反方向增长 |
textDirection | 文本的朝向 |
format | 展示的数字格式: %v:进度的数值 %m:表示剩余时间(单位毫秒) %t:表示总时间(单位毫秒) |
例:按时间增长的进度条、每隔1000ms,让进度条的数值+1,直到100.
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//创建定时器
timer=new QTimer(this);
//关联timeout信号和槽
connect(timer,&QTimer::timeout,this,&Widget::handle);
//启动定时器
timer->start(1000);
}
Widget::~Widget()
{
delete ui;
}
void Widget::handle()
{
//获取进度条的当前值
int val=ui->progressBar->value();
if(val>=100)
{
//终止定时器
timer->stop();
return ;
}
//设置
ui->progressBar->setValue(val+1);
}
- QTimer头文件未被包含,在Widget内定义一个QTimer指针类型的成员变量时,却没有报错未知类型?
在Qt中有一个专门的头文件,用来包含Qt中所有类的前置声明。
如class QWidget;class QPushButton;class QTimer ....(只有类的声明,没有类内部成员的声明)
这个头文件不会直接由用户手动添加,而是在Qt类内部已经被包含。
当我们引入QWidget的头文件,就包含这个专门负责Qt所有类声明的头文件。
有了类型声明,定义类型的指针或引用,只要不实例化/访问类成员编译器就不会报错。
Qt为什么要设计包含前置声明?
为了提高编译速度,#include包含的头文件,编译时会直接展开被包含的头文件,并且一个头文件中可能嵌套包含很多其他头文件,逐个展开会消耗更多的时间。
因此减少头文件数量,就可以有效减少编译时间。
Qt通过前置声明的方式,减少头文件的数量。如上面定义一个QTimer指针(不能访问类成员,要访问成员就要包含头文件),不需要包含QTimer头文件。
- 将指针改为该类型对象时,QTimer报错不完整类型?
前置声明
只需要类的声明,就可以使用该类型的指针/引用作为类的成员变量。
但是不能定义该类型的对象作为成员变量。
class MyClass;
// 只前向声明
class AnotherClass
{
public: MyClass obj;// 错误,编译器无法确定 MyClass 的完整定义
};
这种情况会报错,因为编译器在编译时无法知道 Myclass的大小和布局,因此无法为其分配内存。
例:写一个红色的进度条、使用样式表
QProgressBar::chunk {background: red;}
// QProgressBar::chunk选择器、指定样式对哪个控件生效
// chunk表示进度条会增长的部分
设置背景色之后,数字位置发生改变
设置aliment
实际应用:
读取一个文件,可以获取文件的总大小,每读取一部分数据,更新一次进度条的值。
3. QCalendarWidget 日历
- 功能:日历
- 属性:
selectDate | 当前选中日期 |
minimumDate | 最小日期 |
maximumDate | 最大日期 |
firstDayOfWeek | 日历的第一列是周几 |
gridVisible | 是否显示表格边框 |
selectionMode | 是否允许选择日期 |
navigationBarVisible | 日历上方的标题是否显示 |
horizontalHraderFormat | 日历上方标题显示的日期格式 |
verticalHeaderFormat | 日历第一列显示的内容格式 |
dateEditEnabled | 是否允许日期被编辑 |
- 信号:
selectionChanged(const QDate&) | 当选中的日期发生改变时 |
activated(const QDate&) | 双击有效日期或按下回车键时发出该信号,QDate保存当前选中的日期 |
currentPageChanged(int,int) | 当年份月份改变时,发出该信号,int、int 保存改变后的新年份和月份 |
例:获取选中日期,为selectionChanged(const QDate&)添加槽函数
#include "widget.h"
#include "ui_widget.h"
#include<QDate>
#include<QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QDate date=ui->calendarWidget->selectedDate();
qDebug()<<date;
//设置label的文本
ui->label->setText(date.toString());
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_calendarWidget_selectionChanged()
{
//selectionChanged
QDate date=ui->calendarWidget->selectedDate();
qDebug()<<date;
//设置label的文本
ui->label->setText(date.toString());
}