QT(2.0)

1.常用控件的介绍

1.1 TextEdit

QTextEdit表示多行输入框,也是一个富文本&markdown编辑器,并且能在内容超出编辑框范围时自动提供滚动条。

核心属性

属性

说明

markdown

输入框内持有的内容,支持markdown格式,能够自动的对markdown文本渲染成html

html

输入框持有的内容,可以支持大部分html标签,包括img和table等

placeHolderText

输入框为空时提醒的内容

readOnly

是否是只读的

undoRedoEnable

是否开启undo/redo功能
按下ctrl+z触发undo
按下ctrl+y触发redo

autoFormating

开启自动格式化

tabstopWidth

按下缩进多少控件

overwriteMode

是否开启覆盖写模式

AcceptRichText

是否接受富文本内容

VerticalScrollBarPolicy

垂直方向滚动条的出现策略
Qt::ScrollBarAsNeeded:根据内容自动决定是否需要滚动条。这是默认值
 Qt::ScrollBarAlwaysOff:总是关闭滚动条                                                    
Qt::ScrollBarAlwaysOn:总是显示滚动条                                                   

HorizontalScrollBarPolicy

水平方向滚动条的出现策略
Qt::ScrollBarAsNeeded:根据内容自动决定是否需要滚动条。这是默认值
Qt::ScrollBarAlwaysOff:总是关闭滚动条。
Qt::ScrollBarAlwaysOn:总是显示滚动条。

核心信号

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

当前选中的条目下标
从0开始计算,如果当前没有条目被选中,值为-1

editable

是否允许修改
设为true时,QComboBox的行为就非常接近QLineEdit,也可以设置validator

iconSize

下拉框图标(小三角)的大小

maxCount

最多允许有多少个条目

核心方法

方法

说明

addItem(const QString&)

添加一个条目

currentIndex()

获取当前条目的下标
从0开始计算,如果当前没有条目被选中,值为-1

currentText()

获取当前条目的文本内容

核心信号

方法

说明

Activated(int)
activated(const QString& text)

当用户选择了一个选项时发出

这个时候相当于用户点开下拉框,并且鼠标划过某个选项。

此时还没有确认做出选择

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)

⿏标进⼊元素时触发

在上述介绍中, 涉及到⼀个关键的类, QListWidgetItem . 这个类表⽰ QListWidget 中的⼀个元素.
核⼼⽅法如下, 本质上就是⼀个 "⽂本+图标" 构成的.

方法

说明

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;
    }
    //新生成一个QTreeWidgetItem
    QTreeWidgetItem* 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);
    //创建顶层layout
    QVBoxLayout* 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);

    //创建子layout
    QHBoxLayout* 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);

    //设置列拉伸系数
    //第一列拉伸系数为1
    layout->setColumnStretch(0, 1);
    //第二列拉伸系数为0(即为不拉伸)
    layout->setColumnStretch(1, 0);
    //第三列拉伸系数为3
    layout->setColumnStretch(2, 3);
    this->setLayout(layout);

}

Widget::~Widget()
{
    delete ui;
}

运行结果:

上述效果并非很显眼,我们还可以通过设置行,然后通过QSizePolicy::Expanding尽可能填满整个布局管理器

代码⽰例: 设置垂直⽅向的拉伸系数
1) 编写代码, 创建 6 个按钮, 按照 3 ⾏ 2 列⽅式排列.
使⽤ setSizePolicy 设置按钮的尺⼨策略. 可选的值如下:
QSizePolicy::Ignored : 忽略控件的尺⼨,不对布局产⽣影响。
QSizePolicy::Minimum : 控件的最⼩尺⼨为固定值,布局时不会超过该值。
QSizePolicy::Maximum : 控件的最⼤尺⼨为固定值,布局时不会⼩于该值。
QSizePolicy::Preferred : 控件的理想尺⼨为固定值,布局时会尽量接近该值。
QSizePolicy::Expanding : 控件的尺⼨可以根据空间调整,尽可能占据更多空间。
QSizePolicy::Shrinking : 控件的尺⼨可以根据空间调整,尽可能缩⼩以适应空间。
#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);

    //设置行拉伸系数
    //第一行拉伸系数为1
    layout->setRowStretch(0, 1);
    //第二行拉伸系数为0(即为不拉伸)
    layout->setRowStretch(1, 0);
    //第三行拉伸系数为3
    layout->setRowStretch(2, 3);
    this->setLayout(layout);

}

Widget::~Widget()
{
    delete ui;
}

运行结果:

1.9.4 表格布局

除了上述的布局管理器之外,Qt还提供了QFormLayout, 属于是QGridLayout的特殊情况,专门用于实现两列表单的布局(多用于让用户填写信息的场景,左侧列为提示,右侧列为输入框)

代码⽰例: 使⽤ QFormLayout 创建表单.
1) 编写代码, 创建 QFormLayout , 以及三个 label 和三个 lineEdit
使⽤ addRow ⽅法来添加⼀⾏. 每⾏包含两个控件. 第⼀个控件固定是 QLabel / ⽂本, 第⼆个控件
则可以是任意控件.
如果把第⼀个参数填写为 NULL, 则什么都不显⽰.
#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垂直方向,同上

  • 13
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值