1.常用控件的介绍
1.1 TextEdit
QTextEdit表示多行输入框,也是一个富文本&markdown编辑器,并且能在内容超出编辑框范围时自动提供滚动条。
核心属性
属性 | 说明 |
markdown | 输入框内持有的内容,支持markdown格式,能够自动的对markdown文本渲染成html |
html | 输入框持有的内容,可以支持大部分html标签,包括img和table等 |
placeHolderText | 输入框为空时提醒的内容 |
readOnly | 是否是只读的 |
undoRedoEnable | 是否开启undo/redo功能 |
autoFormating | 开启自动格式化 |
tabstopWidth | 按下缩进多少控件 |
overwriteMode | 是否开启覆盖写模式 |
AcceptRichText | 是否接受富文本内容 |
VerticalScrollBarPolicy | 垂直方向滚动条的出现策略 |
HorizontalScrollBarPolicy | 水平方向滚动条的出现策略 |
核心信号
TextChanged() | 文本内容改变时触发 |
selectionChanged() | 选中范围改变时触发 |
cursorPositionChanged() | 光标移动时触发 |
undoAvailable(bool) | 可以进行undo操作时触发 |
redoAvailable(bool) | 可以进行redo操作时触发 |
copyAvaiable(bool) | 文本被选中/取消选中时触发 |
代码示例:创建一个label和QTextEdit获取用户输入的文本,显示值label中
通过Qt designer创建两个控件出来,然后通过点击QTextEdit转到槽TextChanged(),进行编写代码
void Widget::on_textEdit_textChanged()
{//获取用户输入到textEdit中的文本const QString& text = ui->textEdit->toPlainText();//将获取到的文本设置到label中ui->label->setText(text);
}
运行结果:
还可以看看其他信号的触发情况
void Widget::on_textEdit_copyAvailable(bool b)
{qDebug() << "文本是否被选中:" << b;
}void Widget::on_textEdit_cursorPositionChanged()
{qDebug() << "光标移动";
}void Widget::on_textEdit_undoAvailable(bool b)
{qDebug() << "触发undo";
}void Widget::on_textEdit_currentCharFormatChanged(const QTextCharFormat &format)
{QFont font = format.font(); // 获取当前字符格式的字体信息QColor textColor = format.foreground().color(); // 获取当前字符格式的前景色qDebug() << "Font family: " << font.family();qDebug() << "Font size: " << font.pointSize();qDebug() << "Text color: " << textColor;// 在这里可以根据需要更新界面上的其他部分或者执行其他操作
}
1.2 ComboBox
QcomboBox表示下拉框
核心属性
属性 | 说明 |
currentText | 当前选中的文本 |
CurrentIndex | 当前选中的条目下标 |
editable | 是否允许修改 |
iconSize | 下拉框图标(小三角)的大小 |
maxCount | 最多允许有多少个条目 |
核心方法
方法 | 说明 |
addItem(const QString&) | 添加一个条目 |
currentIndex() | 获取当前条目的下标 |
currentText() | 获取当前条目的文本内容 |
核心信号
方法 | 说明 |
Activated(int) | 当用户选择了一个选项时发出 这个时候相当于用户点开下拉框,并且鼠标划过某个选项。 此时还没有确认做出选择 |
CurrentIndexChanged(int) currentIndecChanged(const QString& text) | 当前选项改变时发出。 此时用户已经明确的选择了一个选项 |
editTextChanged(const QString& text) | 当编辑框中的文本改变时发出 (editable为true时有效) |
代码示例:创建三个下拉框(comboBox)和一个按钮(pushButton),实现用户选中“食物”,点击“确认”按钮后,打印出用户选择的食物
//添加下拉框选项
ui->comboBox->addItem("陕西凉皮");
ui->comboBox->addItem("擀面皮");
ui->comboBox->addItem("凉面");ui->comboBox_2->addItem("素鸡夹馍");
ui->comboBox_2->addItem("锅盔");ui->comboBox_3->addItem("雪碧");
ui->comboBox_3->addItem("可乐");
void Widget::on_pushButton_clicked()
{const QString& Text1 = ui->comboBox->currentText();const QString& Text2 = ui->comboBox_2->currentText();const QString& Text3 = ui->comboBox_3->currentText();qDebug() << Text1 << Text2 << Text3;
}
运行结果:
在很多情况下,我们都需要从文件中加载资源到程序中,我们来模拟实现从本地文件中获取数据,填入到下拉框中
我们在再电脑本地创建一个文件,然后在QT中加在这个文件
//打开文件std::ifstream file("D:/QT/Text.txt");std::string line;//获取文件中的数据while (std::getline(file, line)) {ui->comboBox->addItem(QString::fromStdString(line));}
运行结果:
1.3 SpinBox
使用QSpinBox或者QDoubleSpinBox表示“微调框”,它是带有按钮的输入框, 可以用来输入整数/浮点数,通过点击按钮来修改数值大小
QSpinBox核心属性
属性 | 说明 |
Value | 存储的数值 |
singleStep | 每次调整的“步长”,按下一次按钮变化多少 |
displayInteger | 数字的进制,例如displayInteger设为10,则是按照10进制表示,设为2则为2进制表示 |
minimum | 最小值 |
maximum | 最大值 |
suffix | 后缀 |
prefix | 后缀 |
wrapping | 是否允许换行 |
frame | 是否带边框 |
alignment | 文字对齐方式 |
readOnly | 是否允许修改 |
buttonSymbol | 按钮上的图标 UpDownArrows 上下箭头形式 PlusMinus 加减号形式 NoButtons 没有按钮 |
Accelerated(加速的) | 按下按钮时是否为快速调整模式 |
correctionMode | 输入有误时如何修改. QAbsteactSpinBox::CorrectToPreviousValue:如果用户输入了一个无效的值(例如,在只能显示正整数的SpinBox中输入了负数),那么SpinBox会恢复为上一个有效值。例如,如果SpinBox的初始值是1,用户输入了-1(无效),然后SpinBox会恢复为1。 QAbstractSpinBox::CorrectToNearestValue:如果用户输入了一个无效的值,SpinBox会恢复为最接近的有效值。例如,如果SpinBox的初始值是1,用户输入了-1(无效),那么SpinBox会恢复为0 |
keyboardTrack | 是否开启键盘跟踪. 设为true,每次在输入框输入一个数字,都会触发一次valueChanged()和textChanged()信号 设为false,只有在最终按下enter或者输入框失去焦点,才会触发valueChanged()和textChanged()信号 |
核心信号
信号 | 说明 |
textChanged(QString) | 微调框的文本发生改变时会触发 参数QString带有前缀和后缀 |
valueChanged(int) | 微调框的文本发生改变时会触发 参数int,表示当前的数值 |
代码示例:实现购物车结算
ui->comboBox->addItem("陕西凉皮");ui->comboBox->addItem("擀面皮");ui->comboBox->addItem("凉面");ui->comboBox_2->addItem("素鸡夹馍");ui->comboBox_2->addItem("锅盔");ui->comboBox_3->addItem("雪碧");ui->comboBox_3->addItem("可乐");//设置初始值为1,每次增加份数/1份,最多可以买5份ui->spinBox->setValue(1);ui->spinBox->setRange(1, 5);ui->spinBox_2->setValue(1);ui->spinBox_2->setRange(1, 5);ui->spinBox_3->setValue(1);ui->spinBox_3->setRange(1, 5);ui->spinBox->setCorrectionMode(QAbstractSpinBox::CorrectToNearestValue);
void Widget::on_pushButton_clicked()
{qDebug() <<"当前下单"<<ui->comboBox->currentText() << ":" <<ui->spinBox->value()<<ui->comboBox_2->currentText() <<":" <<ui->spinBox_2->value()<<ui->comboBox_3->currentText() <<":" <<ui->spinBox_3->value();
}
1.4 DateEdit & TimeFdit
使用QDateEdit作为日期的微调框
使用QTimeEdit 作为时间的微调框
使用QDateTimeEdit作为时间日期的微调框
由于这些控件十分相似,我们这里只介绍最全的QDateTimeEdit这个控件
QDateTime核心属性
属性 | 说明 |
dateTime | 时间日期的值,形如2000/1/1 0:00:00 |
date | 单纯日期的值,形如2001/1/1 |
time | 单纯时间的值,形如0:00:00 |
displayFormat | 时间日期格式,形如yyyy/m/d H:mm Y 表示年份 M 表示月份 D 表示日期 H 表示小时 M 表示分钟 S 表示秒 注意:格式化符号,无需记忆,不同语言/库中均存在差异 |
minmumDateTime | 最小时间日期 |
maximumDateTime | 最大日期时间 |
timeSpec | Qt::localTime: 显示本地时间 Qt::UTC: 显示协调世界时(UTC) Qt::OffsetFromUTC:显示相对UTC的偏移量(时差) |
关于本地时间(LocalTime)和协调世界时(UTC)
UTC时间是一个基于原子钟的标准时间,不受地球的自转周期影响,和格林威治时间(GMT)是非常接近的,科学家会通过精密的设备来测量并维护
咱们得计算机内部使用的时间就是基于UTC时间。
本地时间是基于不同时区,对UTC时间做出了一些调整,比如咱们使用的北京时间,位于“东八区”,就需要再UTC时间基础上+8小时的时差
核心信号
信号 | 说明 |
dateChanged(QDate) | 日期改变时触发 |
timeChanged(QTime) | 时间改变时触发 |
dateTimeChanged(QDateTime) | 时间日期任意一个改变时触发 |
代码示例:实现日期计算器
void Widget::on_pushButton_clicked()
{//获取两个时间的日期QDateTime timeOld = ui->dateTimeEdit_old->dateTime();QDateTime timeNew = ui->dateTimeEdit_new->dateTime();//计算时间差int days = timeOld.daysTo(timeNew);int hours = (timeOld.secsTo(timeNew) / 3600) % 24;//设置label中的值QString timeDifference = QString("它们之间相差:") + QString::number(days) +QString("天") + QString::number(hours) + QString("小时");ui->label->setText(timeDifference);
运行结果:
1.5 Dial
使用QDial表示一个旋钮,在一些程序中,通过鼠标拖动旋转,即可完成一些相关的设置
核心属性
属性 | 说明 |
value | 持有的数值 |
minimun | 最小值 |
maximum | 最大值 |
singleStep | 按下方向键的时候改变的步长 |
pageStep | 按下pageUp / pageDown的时候改变的步长 |
sliderPosition | 界面上旋钮显示的初始位置 |
tracking | 外观是否会跟踪数值变化 默认值为true,一般不需要修改 |
wrapping | 是否允许循环调整。 即数值如果超过最大值,是否允许回到最小值。 (调整过程能否“套圈”) |
notchesVisible | 是否显示刻度线 |
notchTarget | 刻度线之间的相对位置。 数字越大,刻度线越稀疏 |
核心信号
属性 | 说明 |
valueChanged(int) | 数值改变时触发 |
rangeChanged(int, int) | 范围变化时触发 |
代码示例:通过Dial实现调节窗口的透明度
//设置可以循环旋转ui->dial->setWrapping(true);//设置刻度线可见ui->dial->setNotchesVisible(true);//设置最大值和最小值ui->dial->setMaximum(100);ui->dial->setMinimum(0);//设置初始值ui->dial->setValue(100);
void Widget::on_dial_valueChanged(int value)
{ui->label->setText(QString("当前透明度:") + QString::number(value));this->setWindowOpacity((double)value / 100);
}
运行结果:
1.6 Slider
使用QSlider表示一个滑动条
与QDial用法相似,均继承自QAbstactSlider
核心属性
属性 | 说明 |
value | 持有的数值 |
minimum | 最小值 |
maximum | 最大值 |
singleStep | 按下方向键的时候改变的步长 |
pageStep | 按下pageUp / pageDown 的时候改变的步长 |
sliderPosition | 滑动条显示的初始位置 |
tracking | 外观是否会跟踪数值变化 默认值为true,一般不需要修改 |
orientation | 滑动条的方向是水平还是垂直 |
invertedAppearance | 是否要翻动滑动条的方向 |
tickPosition | 刻度的位置 |
tickInterval | 刻度的密集程度 |
核心信号
属性 | 说明 |
valueChanged(int) | 数值改变时触发 |
rangeChanged(int, int) | 范围变化时触发 |
代码示例:调整窗口大小
ui->horizontalSlider->setMaximum(800);ui->horizontalSlider->setMinimum(200);ui->horizontalSlider->setSingleStep(100);ui->horizontalSlider->setValue(800);ui->verticalSlider->setMaximum(1024);ui->verticalSlider->setMinimum(224);ui->verticalSlider->setSingleStep(100);ui->verticalSlider->setValue(1024);//改变朝向,默认自上而下ui->verticalSlider->setInvertedAppearance(true);
void Widget::on_horizontalSlider_valueChanged(int value)
{QRect rect = this->geometry();this->setGeometry(rect.x(), rect.y(), value, rect.height());qDebug() << value;
}void Widget::on_verticalSlider_valueChanged(int value)
{QRect rect = this->geometry();this->setGeometry(rect.x(), rect.y(), rect.width(), value);qDebug() << value;
}
运行结果:
1.7 多元素控件
QListWidget, QListView, QTableWidget, QTableView, QTreeWidget, QTreeView
xxWidget 和 xxView 之间的区别
以QTabelWidget 和 QTableView 为例
QTableView 是基于MVC设计的控件, QTableView自身不持有数据, 使用QTableView的时候需要用户创建一个Model对象(比如 QStanfardModel),并且把Model和QTableView关联起来,后续修改Model中的数据就会影响QTableView的显示; 修改QTableView的显示;修改QTableView的显示也会影响到Model中的数据(属于双向绑定)
QTableWidget 则是QTableView的子类,对Model 进行了封装,不需要用户手动创建Model 对像,直接就可以往QTableWidget 中添加数据了
1.7.1 List Widget
使用 QListWidget 能够显示一个纵向的列表,形如:
其中每项都可以被选择
核心属性
属性 | 说明 |
currentRow | 当前被选中的是第几行 |
count | 一共有多少行 |
sortingEnaBled | 是否允许排序 |
isWrapping | 是否允许换行 |
itemAlignment | 元素的对齐方式 |
selectRectVisible | 被选中的元素矩形是否可见 |
spacing | 元素之间的间隔 |
核心方法
方法 | 说明 |
addItem(const QString& label) addItem(QListWidgetItem* item) | 列表中添加元素 |
currentItem() | 返回QListWidgetItem* 表示当前选中的元素 |
setCurrentItem(QListWidgetItem* item) | 设置选中那个元素 |
setCurrentRow(int row) | 设置选中第几行的元素 |
InsertItem(const QString& label, int row) insertItem(QListWidgetItem *item, int row) | 在指定的位置插入元素 |
Item(int row) | 返回QListWidgetItem* 表示第row 行的元素 |
takeItem(int row) | 删除指定的元素,返回QListWidgetItem* 表示的是那个元素被删除 |
核心信号
方法 | 说明 |
currentItemChanged(QListWidgetItem* current, QListWidgetItem* old) | 选中不同元素时会触发. 参数是当前选中的元素和之前选中的元素. |
currentRowChanged(int) | 选中不同元素时会触发. 参数是当前选中元素的⾏数. |
itemClicked(QListWidgetItem* item) | 点击某个元素时触发 |
itemDoubleClicked(QListWidgetItem* item) | 双击某个元素时触发 |
itemEntered(QListWidgetItem* item) | ⿏标进⼊元素时触发 |
方法 | 说明 |
setFont | 设置字体 |
setIcon | 设置图标 |
setHidden | 设置隐藏 |
setSizeHint | 设置尺寸 |
setSelected | 设置是否被选中 |
setText | 设置文本 |
setTextAlignment | 设置文本对齐方式 |
代码示例:实现QListWidget的新增和获取
ui->lineEdit->setPlaceholderText("请输入你想增加的文本");ui->listWidget->addItem("c++");ui->listWidget->addItem("java");ui->listWidget->addItem("python");
void Widget::on_pushButton_clicked()
{// 获取用户输入的文本const QString& text = ui->lineEdit->text();if(text.isEmpty()){return;}ui->listWidget->addItem(text);}void Widget::on_pushButton_2_clicked()
{//获取被选中的行号int row = ui->listWidget->currentRow();ui->listWidget->takeItem(row);
}void Widget::on_listWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
{//此信号之前和当前所选中的文本指针不能为空if(current != nullptr && previous != nullptr){qDebug() << "当前" << current->text() << "之前" << previous->text();}
}
1.7.2 Table Widget
使用QTableWidget表示一个表格控件, 一个表格中包含若干行,每一行又包含若干列, 表格中的每个单元格,是一个QTableWidgetItem对象
QTableWidget核心方法
方法 | 说明 |
item(int row, int column) | 根据行数列数获取指定的QTableWidgetItem* |
setItem(int row, int column, QTableWidget*) | 根据行数列数设置表格中的元素 |
currentItem() | 返回被选中的元素QTableWidgetItem* |
currentRow() | 返回被选中元素时第几行 |
currentColumn() | 返回被选中元素时第几列 |
Row(QTableWidgetItem*) | 获取指定item是第几行 |
Column(QTableWidgetItem*) | 获取指定item是第几列 |
rowCount() | 获取行数 |
columnCount() | 获取列数 |
insertRow(int row) | 在第row行处插入新行 |
insertColumn(int column) | 在第column列插入新列 |
setHorizeontalHeaderItem(int column, QTableWidget*) | 设置指定列的表头 |
setVerticalHeaderItem(int row, QTableWidget* | 设置指定的表头 |
removeRow(int row) | 删除第row行 |
removeColumn(int column) | 删除第column列 |
QTableWidgetItem 核心信号
信号 | 说明 |
cellClicked(int row, int column) | 点击单元格时触发 |
cellDoubleClicked(int row, int column) | 双击单元格是触发 |
cellEntered(int row, int column) | 鼠标进入单元格时触发 |
currentCellChanged(int row, int column, int previousRow, int previousColumn) | 选中不同单元格时触发 |
QTableWidgetItem核心方法
方法 | 说明 |
Row() | 获取当前是第几行 |
Column() | 获取当前是第几列 |
setText(const QString&) | 设置文本 |
setTextAlignment(int) | 设置文本对齐 |
setIcon(const QIcon&) | 设置图标 |
setSelected(bool) | 设置被选中 |
setSizeHints(const Qsize&) | 设置尺寸 |
setFont(const QFont&) | 设置字体 |
代码示例:使用Table WIdget实现表格
ui->lineEdit->setPlaceholderText("请输入新增的列名");//新增三行ui->tableWidget->insertRow(0);ui->tableWidget->insertRow(1);ui->tableWidget->insertRow(2);//新增三列ui->tableWidget->insertColumn(0);ui->tableWidget->insertColumn(1);ui->tableWidget->insertColumn(2);ui->tableWidget->setHorizontalHeaderItem(0, new QTableWidgetItem("姓名"));ui->tableWidget->setHorizontalHeaderItem(1, new QTableWidgetItem("年龄"));ui->tableWidget->setHorizontalHeaderItem(2, new QTableWidgetItem("住址"));ui->tableWidget->setItem(0, 0, new QTableWidgetItem("张三"));ui->tableWidget->setItem(0, 1, new QTableWidgetItem("19"));ui->tableWidget->setItem(0, 2, new QTableWidgetItem("西安"));ui->tableWidget->setItem(1, 0, new QTableWidgetItem("李四"));ui->tableWidget->setItem(1, 1, new QTableWidgetItem("20"));ui->tableWidget->setItem(1, 2, new QTableWidgetItem("杭州"));ui->tableWidget->setItem(2, 0, new QTableWidgetItem("王五"));ui->tableWidget->setItem(2, 1, new QTableWidgetItem("21"));ui->tableWidget->setItem(2, 2, new QTableWidgetItem("北京"));
void Widget::on_pushButton_clicked()
{//获取当前行号int row = ui->tableWidget->rowCount();//插入新的行ui->tableWidget->insertRow(row);
}void Widget::on_pushButton_2_clicked()
{const QString& text = ui->lineEdit->text();//有文本则新增一行if(text.isEmpty()){return;}else {//获取当前的列号int column = ui->tableWidget->columnCount();ui->tableWidget->insertColumn(column);ui->tableWidget->setHorizontalHeaderItem(column, new QTableWidgetItem(text));}}void Widget::on_pushButton_3_clicked()
{int row = ui->tableWidget->currentRow();ui->tableWidget->removeRow(row);
}void Widget::on_pushButton_4_clicked()
{int column = ui->tableWidget->currentColumn();ui->tableWidget->removeColumn(column);
}
运行结果:
1.7.3 Tree Widget
使用QTreeWidget 表示一个树形控件,里面的每个元素,都是一个QTreeWidgetItem,每个QTreeWidgetItem可以包含多个文本和图标,每个文本/图标为一个列。
可以给QTreeWIdget设置顶层节点(顶层节点可以有多个),然后再给顶层节点添加子节点,从而构成树形结构
QTreeWidget核心方法
方法 | 说明 |
clear | 清空所有子节点 |
addTopLevelItem(QTreeWidgetItem* item) | 新增顶层节点 |
topLevelItem(int index) | 获取指定下标的顶层节点 |
topLevelItemCount() | 获取顶层节点个数 |
indexOfTopLevelItem(QTreeWidgetItem* item) | 查询指定节点是顶层节点中的下标 |
tackTopLevelItem(int index) | 删除指定的顶层节点,返回QTreeWidgetItem* 表示被删除的元素 |
currentItem() | 获取到当前选中的节点,返回QTreeWidgetItem* |
setCurrentItem(QTreeWidgetItem* item) | 选中指定节点 |
setExpanded(bool) | 展开/关闭节点 |
setHeaderLabel(const QString& text) | 设置TreeWidget的header名称 |
QTreeWidget 核心信号
信号 | 说明 |
currentItemChanged(QTreeWidgetItem* current, QTreeWidgetItem* old) | 切换选中元素时触发 |
itemClicked(QTreeWidgetItem* item, int col) | 点击元素时触发 |
itemEntered(QTreeWidgetItem* item , int col) | 鼠标进入时触发 |
itemExpanded(QTreeWidgetItem* item) | 元素被展开时触发 |
itemCollapsend(QTreeWidgetItem* item) | 元素被折叠时触发 |
QTreeWidgetItem核心方法
方法 | 说明 |
addChild(QTreeWidgetItem* child) | 新增子节点 |
childCount() | 子节点的个数 |
Chile(int index) | 获取指定下标的子节点,返回QTreeWidgetItem* |
tackChild(int index) | 删除对应下标的子节点 |
removeChile(QTreeWidgetItem* child) | 删除对应的子节点 |
parent() | 获取该元素的父节点 |
代码示例:使用TreeWidget,完成插入(顶层和非顶层)和删除
ui->treeWidget->setHeaderLabel("动物");QTreeWidgetItem* item1 = new QTreeWidgetItem();item1->setText(0, "cat");ui->treeWidget->addTopLevelItem(item1);QTreeWidgetItem* item2 = new QTreeWidgetItem();item2->setText(0, "doy");ui->treeWidget->addTopLevelItem(item2);QTreeWidgetItem* item3 = new QTreeWidgetItem();item3->setText(0, "sheep");ui->treeWidget->addTopLevelItem(item3);
void Widget::on_pushButton_clicked()
{const QString& text = ui->lineEdit->text();if(text.isEmpty()){return;}QTreeWidgetItem* item = new QTreeWidgetItem();item->setText(0, text);ui->treeWidget->addTopLevelItem(item);
}void Widget::on_pushButton_2_clicked()
{//获取输入框文本const QString& text = ui->lineEdit->text();if(text.isEmpty()){return;}//找到父亲节点QTreeWidgetItem* currentItem = ui->treeWidget->currentItem();if(currentItem == nullptr){return;}//新生成一个QTreeWidgetItemQTreeWidgetItem* newItem = new QTreeWidgetItem();//设置文本,添加至父节点中,展开父节点newItem->setText(0, text);currentItem->addChild(newItem);currentItem->setExpanded(true);}void Widget::on_pushButton_3_clicked()
{//获取当前选中的节点QTreeWidgetItem* currentItem = ui->treeWidget->currentItem();//为空则没有选中,返回if(currentItem == nullptr){return;}//获取当前选中节点的父亲节点QTreeWidgetItem* Parent = currentItem->parent();//为空则该节点为顶层节点if(Parent == nullptr){//获取顶层节点的下标int index = ui->treeWidget->indexOfTopLevelItem(currentItem);//删除顶层节点ui->treeWidget->takeTopLevelItem(index);}else{//删除非顶层节点Parent->removeChild(currentItem);}
}
运行结果:
1.8 容器类
1.8.1 QGroupBox
使用QGroupBox实现一个带有标题的分组框,可以把其他的控件放到里面作为一组,这样看起来能更好看一点。
注意:不要将QGroupBox和QButtonGroup混淆.
QGroupBox核心属性
属性 | 说明 |
title | 分组框的标题 |
alignment | 分组框内部内容的对齐方式 |
flat | 是否是“扁平”模式 |
checkable | 是否可选择. 设为true,则是title前方会多出一个可勾选的部分 |
checkeed | 描述分组框的选择状态(前提是checkable为true) |
分组框只是一个用来“美化界面”这样的组件,并不涉及到用户交互和业务逻辑,属于“锦上添花”
代码示例:使用QCroupBox优化之前的点餐界面
ui->groupBox->setTitle("点餐");ui->comboBox->addItem("凉皮");ui->comboBox->addItem("烤肉");ui->spinBox->setValue(1);
void Widget::on_pushButton_clicked()
{qDebug() << ui->comboBox->currentText()<< "份数" << ui->spinBox->value();
}
运行结果:
1.8.2 Tab Widget
使用QTabWidget实现一个带有标签页的控件, 可以往里面添加一些widget,进一步的就可以通过标签页来切换。
TabWidget核心属性
属性 | 说明 |
tabPosition | 标签页所在的位置. North 上方 South 下方 West 左侧 East 右侧 |
currentIndex | 当前选中了第几个标签页(从0开始计算) |
currentTabText | 当前选中的标签页的文本 |
currentTabName | 当前选中的标签页的图标 |
currentTabToolTip | 当前选中的标签页的提示信息 |
tabsCloseable | 标签页是否关闭 |
moveable | 标签页是否可以移动 |
核心信号
属性 | 说明 |
currentChanged(int) | 在标签页发生切换时触发,参数为点击的选项卡编号 |
tabBarClicked(int) | 在点击选项卡的标签条的时候触发,参数为被点击的选项卡编号 |
tabBarDoubleClicked(int) | 在双击选项卡的标签页的时候触发,参数为被点击的选项卡编号 |
tabCloseRequest(int) | 在标签页关闭时触发,参数为被关闭的选项卡编号 |
代码示例:使用标签页管理多组控件
1)在界面上创建一个QTabWidget,和两个按钮。按钮的objectName为pushButton_add和pushButton_remove
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTabWidget>
#include <QDebug>
#include <QLabel>
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);connect(ui->pushButton_add, &QPushButton::clicked, this, &MainWindow::PushButtonAdd);connect(ui->pushButton_remove, &QPushButton::clicked, this, &MainWindow::PushButtonremove);QLabel* label_1 = new QLabel(ui->tab);label_1->setGeometry(100, 100, 200, 50);label_1->setText("标签1");QLabel* label_2 = new QLabel(ui->tab_2);label_2->setGeometry(100, 100, 200, 50);label_2->setText("标签2");
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::PushButtonAdd()
{/* 获取当前所存在的tab页面 */int count = ui->tabWidget->count();/* 生成新的tab页面,并将其添加至QTabWidget中 */QWidget* tag = new QWidget();ui->tabWidget->addTab(tag, QString("tab") + QString::number(count + 1));QLabel* label = new QLabel(tag);label->setGeometry(100, 100, 200, 50);label->setText(QString("标签") + QString::number(count + 1));ui->tabWidget->setCurrentIndex(count);
}void MainWindow::PushButtonremove()
{/* 获取当前选中的页面号,并删除它 */int index = ui->tabWidget->currentIndex();ui->tabWidget->removeTab(index);
}
运行结果:
1.9 布局管理器
之前使用Qt在界面上创建的控件, 都需要通过“绝对定位”的方式来设定的。
也就是每个控件所在的位置,都需要计算坐标,最后通过move和setGeometry方式来设置
这种设定方式其实并不是很方便,尤其在界面内容较多的情况下,不好计算,而且一个窗口大小往往是可以调整的,按照绝对定位的方式,也无法自适应窗口大小
因此Qt引入“布局管理器”(Layout)机制, 来解决上述问题
1.9.1 垂直布局
使用QVBoxLayout 表示垂直的布局管理器,V是vertical的缩写
属性 | 说明 |
layoutLeftMargin | 左侧边距 |
layoutRightMargin | 右侧边距 |
layoutTopMargin | 上方边距 |
layoutBottomMargin | 下方边距 |
layoutSpacing | 相邻元素之间的间距 |
Layout只是用于界面布局,并没有提供信号
代码示例:使用QVBoxLayout管理多个控件
1)编写代码,创建布局管理器和三个按钮,并且把按钮添加到布局管理器中。
使用addWidget 把控件添加到布局管理器中
使用setLayout设置该布局管理器到widget中
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
#include <QVBoxLayout>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QPushButton* button_1 = new QPushButton("按钮1");QPushButton* button_2 = new QPushButton("按钮1");QPushButton* button_3 = new QPushButton("按钮1");QVBoxLayout* layout = new QVBoxLayout();layout->addWidget(button_1);layout->addWidget(button_2);layout->addWidget(button_3);this->setLayout(layout);
}Widget::~Widget()
{delete ui;
}
运行结果:
通过上述代码的方式,只能给这个widget设定一个布局管理器,实际上也是可以通过Qt Design在一个窗口中创建多个布局管理器
代码示例:
创建两个QVBoxLayout
1)在界面上创建两个QVBoxLayout,每个QVBoxLayout各放三个按钮
运行结果:
实际上一个Widget只能创建一个QVBoxLayout,那我我们这个是怎么实现的呢
注:这种情况下layout并非是窗口widget的布局管理器,因此无法随窗口的大小而改变
1.9.2 水平布局
使用QHBoxLayout表示垂直的布局管理器,H是horizontal的缩写,核心属性(和QVBoxLayout一致)
属性 | 说明 |
layoutLeftMargin | 左侧边距 |
layoutRightMargin | 右侧边距 |
layoutTopMargin | 上方边距 |
layoutBottomMargin | 下方边距 |
layoutSpacing | 相邻元素之间的间距 |
代码示例:嵌套的layout
1) 在代码中创建addLayout,给其layout中添加子layot
#include "widget.h"
#include "ui_widget.h"
#include <QHBoxLayout>
#include <QPushButton>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//创建顶层layoutQVBoxLayout* layout = new QVBoxLayout();//创建按钮QPushButton* button_1 = new QPushButton("按钮1");QPushButton* button_2 = new QPushButton("按钮2");//添加到widget中this->setLayout(layout);layout->addWidget(button_1);layout->addWidget(button_2);//创建子layoutQHBoxLayout* layout_2 = new QHBoxLayout();QPushButton* button_3 = new QPushButton("按钮3");QPushButton* button_4 = new QPushButton("按钮4");layout_2->addWidget(button_3);layout_2->addWidget(button_4);//子layout添加到父layout中layout->addLayout(layout_2);
}Widget::~Widget()
{delete ui;
}
运行结果:
将其相互结合之后就可以做出复杂界面了
1.9.3 网格布局
Qt中提供了QGrdLayout用来实现网格布局的效果,可以达到M*N的这种效果。
核心属性
整体和QVBoxLayout以及QHBoxLayout相似,但是设置spacing的时候是按照垂直水平两个方向来设置的
属性 | 说明 |
layoutLeftMargin | 左侧边距 |
layoutRightMargin | 右侧边距 |
layoutTopMargin | 上方边距 |
layoutBottomMargin | 下方边距 |
layoutHorizontalSpacing | 相邻元素之间水平方向的间距 |
layoutVerticalSpacing | 相邻元素之间垂直方向的间距 |
layoutRowStretch | 行方向的拉伸系数 |
layoutColumnStrectch | 列方向的拉伸系数 |
代码示例:使用QGridLayout管理元素
1)代码中创建QGridLayout和4个按钮(使用addWidget添加控件到布局管理器的时候,指定两个坐标,分别为第几行和第几列)
#include "widget.h"
#include "ui_widget.h"
#include <QGridLayout>
#include <QPushButton>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QGridLayout* layout = new QGridLayout();QPushButton* button_1 = new QPushButton("按钮1");QPushButton* button_2 = new QPushButton("按钮2");QPushButton* button_3 = new QPushButton("按钮3");QPushButton* button_4 = new QPushButton("按钮4");layout->addWidget(button_1, 0, 0);layout->addWidget(button_2, 0, 1);layout->addWidget(button_3, 1, 0);layout->addWidget(button_4, 1, 1);this->setLayout(layout);}Widget::~Widget()
{delete ui;
}
运行结果:
注:设置行和列的时候,如果设置的是一个很大的值,但是这个值和上一个值之间并没有其他的元素,那么并不会在中间腾出额外的控件
如图所示
代码示例:设置QGridLayout中的大小比例
1)创建6个按钮,按照2行3列排放,使用setColumnStretch设置每一列的拉伸值
#include "widget.h"
#include "ui_widget.h"
#include <QGridLayout>
#include <QPushButton>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QGridLayout* layout = new QGridLayout();QPushButton* button_1 = new QPushButton("按钮1");QPushButton* button_2 = new QPushButton("按钮2");QPushButton* button_3 = new QPushButton("按钮3");QPushButton* button_4 = new QPushButton("按钮4");QPushButton* button_5 = new QPushButton("按钮5");QPushButton* button_6 = new QPushButton("按钮6");layout->addWidget(button_1, 0, 0);layout->addWidget(button_2, 0, 1);layout->addWidget(button_3, 0, 2);layout->addWidget(button_4, 1, 0);layout->addWidget(button_5, 1, 1);layout->addWidget(button_6, 1, 2);//设置列拉伸系数//第一列拉伸系数为1layout->setColumnStretch(0, 1);//第二列拉伸系数为0(即为不拉伸)layout->setColumnStretch(1, 0);//第三列拉伸系数为3layout->setColumnStretch(2, 3);this->setLayout(layout);}Widget::~Widget()
{delete ui;
}
运行结果:
上述效果并非很显眼,我们还可以通过设置行,然后通过QSizePolicy::Expanding尽可能填满整个布局管理器
#include "widget.h"
#include "ui_widget.h"
#include <QGridLayout>
#include <QPushButton>
#include <QSizePolicy>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QGridLayout* layout = new QGridLayout();QPushButton* button_1 = new QPushButton("按钮1");QPushButton* button_2 = new QPushButton("按钮2");QPushButton* button_3 = new QPushButton("按钮3");QPushButton* button_4 = new QPushButton("按钮4");QPushButton* button_5 = new QPushButton("按钮5");QPushButton* button_6 = new QPushButton("按钮6");layout->addWidget(button_1, 0, 0);layout->addWidget(button_2, 0, 1);layout->addWidget(button_3, 1, 0);layout->addWidget(button_4, 1, 1);layout->addWidget(button_5, 2, 0);layout->addWidget(button_6, 2, 1);//设置按钮的sizePolicy,此时按钮的水平方向和垂直方向都会尽量展开button_1->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);button_2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);button_3->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);button_4->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);button_5->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);button_6->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);//设置行拉伸系数//第一行拉伸系数为1layout->setRowStretch(0, 1);//第二行拉伸系数为0(即为不拉伸)layout->setRowStretch(1, 0);//第三行拉伸系数为3layout->setRowStretch(2, 3);this->setLayout(layout);}Widget::~Widget()
{delete ui;
}
运行结果:
1.9.4 表格布局
除了上述的布局管理器之外,Qt还提供了QFormLayout, 属于是QGridLayout的特殊情况,专门用于实现两列表单的布局(多用于让用户填写信息的场景,左侧列为提示,右侧列为输入框)
#include "widget.h"
#include "ui_widget.h"
#include <QLabel>
#include <QLineEdit>
#include <QFormLayout>
#include <QPushButton>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QLabel* lable_1 = new QLabel("姓名");QLabel* lable_2 = new QLabel("班级");QLabel* lable_3 = new QLabel("年龄");QLineEdit* lineEdit_1 = new QLineEdit();QLineEdit* lineEdit_2 = new QLineEdit();QLineEdit* lineEdit_3 = new QLineEdit();QPushButton* button = new QPushButton("确认");QFormLayout* layout = new QFormLayout();layout->addRow(lable_1, lineEdit_1);layout->addRow(lable_2, lineEdit_2);layout->addRow(lable_3, lineEdit_3);layout->addRow(nullptr, button);this->setLayout(layout);}Widget::~Widget()
{delete ui;
}
运行结果:
1.9.5 Spacer
使用布局管理器的时候,可能需要在控件之间,添加一段空白,就可以使用QSpacerItem来表示
属性 | 说明 |
width | 宽度 |
height | 高度 |
hData | ⽔平⽅向的 sizePolicy • QSizePolicy::Ignored : 忽略控件的尺⼨,不对布局产⽣影响。 • QSizePolicy::Minimum : 控件的最⼩尺⼨为固定值,布局时不会超过该值。 • QSizePolicy::Maximum : 控件的最⼤尺⼨为固定值,布局时不会⼩于该值。 • QSizePolicy::Preferred : 控件的理想尺⼨为固定值,布局时会尽量接近该 值。 • QSizePolicy::Expanding : 控件的尺⼨可以根据空间调整,尽可能占据更多空 间。 • QSizePolicy::Shrinking : 控件的尺⼨可以根据空间调整,尽可能缩⼩以适应 空间。 |
vData | 垂直方向,同上 |