目录
前言:
在Qt中,为了进一步实现界面与用户的交互,可以使用输入类控件,输入类控件可以获取用户输入的信息,从而将该信息传递给程序做进一步分析。输入类控件作为界面中最重要的控件,因为实际中使用计算机,必须得有输入框,否则用户是无法使用计算机的。
1、QLineEdit
QLineEdit表示单行输入框,这是最经典的输入框,用户可以在框框中输入文本,但是当文本内容超出输入框界限时,不会自动换行,也不会提供滚动条。
QLineEdit属性介绍如下:
text
| 表示输⼊框中的⽂本内容 |
inputMask
|
表示输⼊框中的⽂本
格式
|
maxLength
| 表示输⼊框中的⽂本内容的最大长度 |
frame
|
是否给输入框添加边框
|
echoMode
| 文本内容的显示方式(具体用法见下文) |
cursorPosition
|
光标所在位置
|
alignment
|
文本对齐方式,比如⽔平和垂直⽅向的对齐
|
dragEnabled
|
是否允许拖拽输入框
|
readOnly
| 是否允许修改文本内容 |
placeHolderText
|
当输⼊框内容为空的时候,显示什么样的提示信息
|
clearButtonEnabled
| 输入框右侧是否出现“情况内容”的按钮 |
当对输入框进行相关操作时,QLineEdit会发出对应的信号,信号介绍如下:
void cursorPositionChanged(int old, int new)
|
当⿏标移动时发出此信号,old为先前的位置,new为新位置
|
void editingFinished()
|
当按返回或者回⻋键时,或者行编辑失去焦点时,发出此信号
|
void returnPressed()
|
当返回或回⻋键按下时发出此信号,如果设置了验证器, 必须要验证通过, 才能触发
|
void selectionChanged()
|
当选中的⽂本发生改变时,发出此信号
|
void textChanged(const QString &text)
|
当QLineEdit中的⽂本改变时,发出此信号,text是新的⽂本。 在代码层面上的文本修改
能够
触发这个信号
|
void textEdited(const QString &text))
|
当QLineEdit中的⽂本改变时,发出此信号,text是新的⽂本。 在代码层面上的文本修改
不能
触发这个信号
|
1.1 使用QLineEdit
模拟一个录入个人信息的界面,该界面主要由用户名、密码、电话(三个输入框QLineEdit),和性别(两个单选按钮QRadioButtion),以及确认(一个单击按钮QPushButton)构成。使用ui文件生成的界面如下:
在代码中优化上述界面,比如当输入框为空时可以显示一些提示,以及输入内容后可以快速清空输入框中的内容,并且在我们平时输入密码和电话时,可以发现输入的密码不会显示表现出来,而是用统一的字符进行屏蔽,输入电话时会有明确的格式要求,比如000-0000-0000,做好上述这些优化可以方便用户对界面的使用。
在widget.cpp中优化界面的代码如下:
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//显示提示信息
ui->lineEdit_name->setPlaceholderText("请输入用户名");
ui->lineEdit_password->setPlaceholderText("请输入密码");
ui->lineEdit_tel->setPlaceholderText("请输入电话号码");
//生成清空输入框内容的按键
ui->lineEdit_name->setClearButtonEnabled(true);
ui->lineEdit_password->setClearButtonEnabled(true);
ui->lineEdit_tel->setClearButtonEnabled(true);
//对密码输入框进行特殊处理
ui->lineEdit_password->setEchoMode(QLineEdit::Password);
//对电话输入框进行格式处理
ui->lineEdit_tel->setInputMask("000-0000-0000");
}
Widget::~Widget()
{
delete ui;
}
运行结果:
并且可以将选中的信息打印到屏幕上,需要实现“确认”按钮的槽函数,代码如下:
void Widget::on_pushButton_clicked()
{
QString gender = ui->radioButton_male->isChecked() ? "男" : "⼥";
qDebug() << "姓名: " << ui->lineEdit_name->text()
<< "密码: " << ui->lineEdit_password->text()
<< "性别: " << gender
<< "手机: " << ui->lineEdit_tel->text();
}
点击确认按钮后,可以在输出窗口中看到打印信息,运行结果:
1.2 正则表达式
正则表达式是一种对字符串格式进行强有力约束的手段,正则表达式本身也是一个字符串,他的作用就是严格要求数据的合法性。比如上述代码中使用inputMask对电话框进行格式限制,让电话号码只能按照规定的格式输入,而正则表达式的约束力可以比inputMask更严格,比如正则表达式规定电话号码的第一位必须是1,如果输入的电话号码第一位不是1,说明这个电话号码是有误的,因此整个信息就无法提交,除非输入正确的电话号码。
使用正则表达式的思路:在上述代码中可以加入正则表达式,首先创建一个正则表达式对象(QRegExp),然后用该对象创建一个验证器对象(QRegExpValidator),可以理解为验证器就是正则表达式的载体。
接着将验证器设置到要约束的输入框中,使用信号textEdited,每次对输入框的内容做更改都要做验证,因此可以在该信号的槽函数中做验证:调用验证器对象的接口State validate(QString&,int&)来验证文本是否符合规定,其中形参QString保存的就是当前输入框文本的内容,若合格则返回一个枚举QValidator::Acceptable,若不合格则返回QValidator::Invalid。
正则表达式代码实现:
#include "widget.h"
#include "ui_widget.h"
#include <QRegExp>
#include <QRegExpValidator>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
ui->pushButton->setEnabled(false);//最开始按钮是不可选择的,因为输入框没有任何文本
QRegExp reg("^1\\d{10}$");//创建正则表达式对象
QRegExpValidator* rege = new QRegExpValidator(reg);//创建验证器对象
ui->lineEdit->setValidator(rege);//给输入框设置验证器
}
Widget::~Widget()
{
delete ui;
}
//每次对输入框的文本做更改都会执行这个槽函数
void Widget::on_lineEdit_textEdited(const QString &arg1)
{
QString s = arg1;
int pos = 0;
if(ui->lineEdit->validator()->validate(s,pos)==QValidator::Acceptable)
{
ui->pushButton->setEnabled(true);//验证成功,打开按钮
}
else
{
ui->pushButton->setEnabled(false);//验证失败,关闭按钮
}
}
这里解释一下上述正则表达式的规则:
· ^ 表示以某个字符开头,^后面跟着的1,意思就是以1开头
· \d 表示数字,为了在C++字符串中使用,需要使用\进行转义
· {10}表示前面的内容重复出现10次,即\d数字要重复出现10次.
· $表示结尾
运行结果:
2、QTextEdit
QTextEdit表示多行输入框,他还支持html文本格式,而QLineEdit只能表示纯文本格式。并且编辑框中的文本内容超出编辑框范围则会⾃动提供滚动条。
QTextEdit的属性介绍如下:
markdown
| 可以将markdown格式的内容转换成html格式 |
html
| 支持html标签 |
placeHolderText
|
输⼊框为空时提示的内容
|
readOnly
| 是否只读 |
undoRedoEnable
|
是否开启 undo / redo 功能,按下 ctrl + z 触发 undo ,按下 ctrl + y 触发 redo
|
autoFormating
|
开启⾃动格式化
|
tabstopWidth
|
缩进占多少空间
|
overwriteMode
|
是否开启覆盖写模式
|
acceptRichText
|
是否接收富⽂本内容
|
verticalScrollBarPolicy
| 垂直⽅向滚动条的出现策略 |
horizontalScrollBarPolicy
|
⽔平⽅向滚动条的出现策略
|
QTextEdit的核心信号:
textChanged()
|
⽂本内容改变时触发
|
selectionChanged()
|
选中输入框里的内容时触发
|
cursorPositionChanged()
|
光标移动时触发
|
undoAvailable(bool)
|
可以进⾏ undo 操作时触发
|
redoAvailable(bool)
|
可以进⾏ redo 操作时触发
|
copyAvaiable(bool)
|
⽂本被选中/取消选中时触发
|
2.1 使用QTextEdit
创建一个QTextEdit和一个QLabel,实现往QTextEdit里写内容时会将该内容复制到QLabel中,界面设计如下:
代码实现:
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
//当多行输入框的文本内容发生改变时,调用此函数
void Widget::on_textEdit_textChanged()
{
ui->label->setText(ui->textEdit->toPlainText());
}
运行结果:
2.2 测试QTextEdit的信号
首先在界面中创建一个QTextEdit控件,然后直接右键点击转到槽,在每个槽中打印相关信息,方便观察触发了哪个信号,如下图:
测试代码如下:
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_textEdit_textChanged()//修改文本内容调用此函数
{
qDebug() << "[textChanged] " << ui->textEdit->toPlainText();
}
void Widget::on_textEdit_selectionChanged()//选中文本的范围发生变化调用此函数
{
//通过这个QTextCursor对象可以获取到当前光标位置和选中的内容
const QTextCursor& cursor = ui->textEdit->textCursor();
qDebug() << "[selectionChanged] " << cursor.selectedText();//打印选中内容
}
void Widget::on_textEdit_cursorPositionChanged()//光标移动时调用此函数
{
const QTextCursor& cursor = ui->textEdit->textCursor();//逻辑同上
qDebug() << "[cursorPositionChanged] " << cursor.position();//打印光标位置
}
void Widget::on_textEdit_undoAvailable(bool b)//按下ctrl + z调用此函数
{
qDebug() << "[undoAvailable] " << b;
}
void Widget::on_textEdit_redoAvailable(bool b)//按下ctrl + y调用此函数
{
qDebug() << "[redoAvailable] " << b;
}
void Widget::on_textEdit_copyAvailable(bool b)//⽂本被选中或取消选中时调用此函数
{
qDebug() << "[copyAvailable] " << b;
}
测试①:添加或删除输入框中的内容时,会发送textChanged和cursorPositionChanged信号,运行结果如下:
测试②:选中⼀段⽂本时,会发送cursorPositionChanged , selectionChanged , copyAvailable三个信号,运行结果如下:
测试③:测试ctrl+z和ctrl+y,运行结果如下:
3、QComboBox
QComboBox表示下拉框,框里的文本内容通过下拉的形式显示出来,属性介绍如下:
currentText
|
当前选中的条目⽂本内容,条目指的是下拉之后的选项
|
currentIndex
|
当前选中的条⽬下标
|
editable
|
是否允许修改条目文本内容
|
iconSize
|
下拉框图标的大小
|
maxCount
|
最多允许有多少个条⽬
|
QComboBox的核心信号:
activated(int)
|
当用户选择了⼀个条目时发出,int是该条目的下标
|
activated(const QString & text) | 当用户滑过某个条目时(此时还未选中)发出 |
currentIndexChanged(int)
|
当前条目改变时发出,int改变后的条目的下标
|
currentIndexChanged(const QString& text)
|
当用户明确的选择了⼀个条目发出,text保存的是该条目的内容
|
editTextChanged(const QString& text)
| 当条目内容发生改变时发出 |
3.1 使用QComboBox
模拟一个点餐界面,可以在下拉框中选择条目,选择完毕后点击确认按钮即可在输出窗口中打印出选择的信息,界面设计如下:
代码优化如下:
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//炒饭类
ui->comboBox->addItem("蛋炒饭");
ui->comboBox->addItem("青椒肉丝炒饭");
ui->comboBox->addItem("酸菜牛肉炒饭");
//饮料类
ui->comboBox_2->addItem("可乐");
ui->comboBox_2->addItem("雪碧");
ui->comboBox_2->addItem("橙汁");
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_clicked()
{
qDebug()<<ui->comboBox->currentText();
qDebug()<<ui->comboBox_2->currentText();
}
运行结果:
3.2 测试QComboBox的信号
当选中下拉框的一个条目时,测试activated和currentIndexChanged信号,首先快速创建一个下拉框,并且给下拉框中生成几个条目,方法如下:
然后右键该下拉框,点击转到槽,快速生成activated和currentIndexChanged信号的槽函数:
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_comboBox_activated(int index)
{
qDebug()<<index;
}
void Widget::on_comboBox_currentIndexChanged(const QString &arg1)
{
qDebug()<<arg1;
}
运行结果:
即使没有点击确认按钮,但是依然可以实现打印到屏幕上的功能。
4、QSpinBox
QSpinBox表示微调框,通过向上调整、向下调整两个按钮,可以使文本中的数值增大或减少,这样规定了QSpinBox的文本必须是整数或者小数。QSpinBox属性介绍如下:
value
| 文本中的数值 |
singleStep
|
每次调整的 "步⻓",按一次按钮会让数据变化多少.
|
displayInteger
|
数值
的进制,例如displayInteger设为10,则数值是按照 10 进制表⽰
|
minimum
| 数值的最小值 |
maximum
| 数值的最大值 |
suffix
| 后缀 |
prefix
| 前缀 |
QSpinBox的核心信号:
textChanged(QString)
|
微调框的⽂本发⽣改变时会触发,参数 QString 带有 前缀 和 后缀.
|
valueChanged(int)
|
微调框的⽂本发⽣改变时会触发,参数 int,表⽰当前的数值
|
4.1 使用QSpinBox
给上述点餐界面加上一个QSpinBox,作为品类的份量。界面设计如下:
代码如下:
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
ui->fssfd->setValue(1);//设置初始值
ui->fssfd->setRange(1, 5);//设置范围
ui->fssfd_2->setValue(1);
ui->fssfd_2->setRange(1, 5);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_clicked()
{
qDebug() << "当前下单的内容: "
<< ui->comboBox->currentText() << ": " << ui->fssfd->value()<<" "
<< ui->comboBox_2->currentText() << ": " << ui->fssfd_2->value();
}
运行结果:
4.2 测试QSpinBox的信号
测试textChanged和valueChanged信号,代码如下:
void Widget::on_fssfd_2_textChanged(const QString &arg1)
{
qDebug()<<arg1;
}
void Widget::on_fssfd_2_valueChanged(int arg1)
{
qDebug()<<arg1;
}
运行结果:
每当更改QSpinBox里的文本内容时都会触发上述两个信号,其中一个以字符串的形式记录更改后的内容,一个以int的形式记录更改后的内容。
5、QDateTimeEdit
QDateTimeEdit是记录时间日期的微调框,他的控件形式和QSpinBox是一样的,如下图:
QDateTimeEdit属性介绍如下:
dateTime
| 框中的文本内容 |
date
|
单纯⽇期的值
|
time
|
单纯时间的值
|
displayFormat
|
时间⽇期格式,比如yyyy/M/d H:mm
|
minimumDateTime
|
最小时间⽇期
|
maximumDateTime
|
最大时间⽇期
|
timeSpec
| 不同的时间规则 |
QDateTimeEdit核心信号:
dateChanged(QDate)
|
⽇期改变时触发
|
timeChanged(QTime)
|
时间改变时触发
|
dateTimeChanged(QDate Time)
|
时间⽇期任意⼀个改变时触发
|
5.1 使用QDateTimeEdit
模拟一个日期计算机,用新的QDateTimeEdit时间日期减去旧的QDateTimeEdit控件时间日期,从而计算出旧日期和新日期之间的天数和小时数。界面设计如下:
代码如下:
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_clicked()
{
// 1. 先获取到这两个输入框之间的时间都是啥.
QDateTime timeOld = ui->dateTimeEdit->dateTime();
QDateTime timeNew = ui->dateTimeEdit_2->dateTime();
// 2. 计算日期的差值
// int days = timeOld.daysTo(timeNew);
int seconds = timeOld.secsTo(timeNew);
// 3. 要把秒数换算成小时
int hours = (seconds / 3600) % 24;
int days = (seconds / 3600) / 24;
// 4. 把计算结果放到 label 中
ui->label->setText(QString("结果为:")+QString :: number(days)
+ QString("天 零")+QString :: number(hours)+QString("小时"));
}
运行结果:
QDateTimeEdit的信号用法和上文控件的用法逻辑是一样的,都是当文本内容有变化后触发,这里就不再举例了。
6、QDial
QDial表示旋钮,和一般的按钮不同的是,QDial是通过鼠标点击旋转进行触发的。好比旧式水龙头的开关,通过旋转开头来控制水流大小。也通过旋转QDial,来控制程序实现的粒度。如下图:
QDial不仅可以通过鼠标进行旋转,还可以通过键盘上的方向键进行旋转。QDial属性介绍:
value
|
持有的数值,一般是给内部看的,外部看不到该数值
|
minimum
| value的最小值 |
maximum
| value的最大值 |
singleStep
|
按下⽅向键的时候改变的步⻓
|
pageStep
|
按下 pageUp / pageDown 的时候改变的步⻓
|
sliderPosition
|
界⾯上旋钮显⽰的 初始位置
|
tracking
|
外观是否会跟踪数值变化
|
wrapping
|
是否允许循环调整
|
notchesVisible
|
是否在控件周围显示刻度线
|
notchTarget
|
刻度线之间的相对位置
|
QDial核心信号:
valueChanged(int)
|
数值改变时触发
|
rangeChanged(int, int)
|
范围变化时触发
|
6.1 使用QDial
实现一个可以通过QDial来调整窗口透明度的代码,使用setWindowOpacity函数来调整透明度,其中传给该函数的值是1.0则表示完全不透明,是0.0则表示完全透明,而QDial就是控制这个值的大小。代码如下:
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
ui->dial->setValue(100);
ui->dial->setMinimum(0);
ui->dial->setMaximum(100);
ui->dial->setWrapping(true);
ui->dial->setNotchesVisible(true);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_dial_valueChanged(int value)
{
qDebug()<<value;
ui->label->setText("当前不透明度:"+QString::number(value));
this->setWindowOpacity((double)value/100);
}
运行结果:
7、QSlider
QSlider表示一个滑动条,他的逻辑和QDial是一样的,只不过QDial是旋转,而QSlider是滑动。他们都是继承QAbstractSlider,所以他们的属性基本都一样的,区别在于QSlider多了以下属性:
orientation
|
滑动条的⽅向是⽔平还是垂直
|
invertedAppearance
|
是否要翻转滑动条的⽅向
|
tickPosition
|
设置刻度的位置
|
tickInterval
|
刻度的密集程度
|
QSlider有两种控件:1、水平QSlider,2、垂直QSlider。如下图:
QSlider的信号和QDial的信号基本一致,这里就不再举例了。
7.1 使用QSlider
也是模拟一个通过QSlider来调整窗口的透明度代码,代码如下:
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//设置刻度线
ui->horizontalSlider->setTickPosition(QSlider::TickPosition::TicksAbove);
ui->horizontalSlider->setMaximum(100);
ui->horizontalSlider->setMinimum(0);
ui->horizontalSlider->setValue(100);//设置初始值
ui->horizontalSlider->setInvertedAppearance(true);//反转滑动条
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_horizontalSlider_valueChanged(int value)
{
ui->label->setText("当前窗口的不透明度:"+QString::number(value));
this->setWindowOpacity((double)value/100);
}
运行结果:
结语
以上就是关于输入类控件的讲解,输入类控件涉及到与用户的直接交互,因此输入类控件的使用离不开其信号,并且其信号种类繁多,给到开发者足够的空间去开发各种逻辑的界面,但实际中只需要记住几个常用信号就可以满足大部分的场景。
最后如果本文有遗漏或者有误的地方欢迎大家在评论区补充,谢谢大家!!