QT(2.0)

news2025/1/22 12:45:24

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垂直方向,同上

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1989230.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[Leetcode 215][Medium]-数组中的第K个最大元素-快排/小根堆/堆排序

一、题目描述 原题地址 二、整体思路 &#xff08;1&#xff09;快排 对于SELECT K问题&#xff0c;可以通过三路快排解决&#xff0c;快排可以把一个元素放至按升序排序的数组正确的位置&#xff0c;左边为小于该元素的元素集合&#xff0c;右边为大于该元素的元素集合。 三…

朋克养生,现代男人为何对生可乐泡枸杞情有独钟

在当今快节奏、高压力的社会环境中&#xff0c;朋克养生这一独特的养生方式悄然兴起&#xff0c;尤其在年轻男性群体中备受青睐。其中&#xff0c;生可乐泡枸杞这一不乏创意的养生方法&#xff0c;更是成为不少现代男人追求健康与乐趣并存的象征。朋克养生不仅仅是一种外在的行…

lvs的防火墙标记解决轮询调度问题

错误示范 ipvsadm -A -t 192.168.0.200:80 -s rr ipvsadm -a -t 192.168.0.200:80 -r 192.168.0.10:80 -g ipvsadm -a -t 192.168.0.200:80 -r 192.168.0.20:80 -g ipvsadm -A -t 192.168.0.200:443 -s rr ipvsadm -a -t 192.168.0.200:443 -r 192.168.0.10:80 -g ipvsadm -a …

CVE-2024-39877:Apache Airflow 任意代码执行

Apache Airflow 是一个开源平台&#xff0c;用于以编程方式编写、调度和监控工作流。虽然它提供了管理复杂工作流的强大功能&#xff0c;但它也存在安全漏洞。一个值得注意的漏洞 CVE-2024-39877 是 DAG&#xff08;有向无环图&#xff09;代码执行漏洞。这允许经过身份验证的 …

游戏ttf字体瘦身脚本

游戏中通常会用到某种特定字体&#xff0c;而某些字体动则10M&#xff0c;对某些游戏(尤其是小游戏)来讲是无法忍受的&#xff0c;此文章主要讲述上个项目中制作的字体裁剪脚本 工具git地址 配置信息(config.json) { // 文本内容(可能为多语言表导出的内容)"txtFile&qu…

常用API(三)

对于常见API的学习&#xff0c;主要学习了关于时间和日期的传统和新增APi 目录 1.Math 2.System 3.Runtime 4.日期和时间 &#xff08;1&#xff09;JDK8前传统时间API [1] Date [2] SimpledateFormat [3]Calendar &#xff08;2&#xff09;JDK8后新增时间API [1]代替…

JeecgBoot低代码平台简单记录

BasicModal弹窗 Usage 由于弹窗内代码一般作为单文件组件存在&#xff0c;也推荐这样做&#xff0c;所以示例都为单文件组件形式 注意v-bind"$attrs"记得写&#xff0c;用于将弹窗组件的attribute传入BasicModal组件 attribute&#xff1a;是属性的意思&#xff0c;…

嵌入式学习之线程和同步互斥机制

一. 线程的概念 进程的上下文切换&#xff1a; a.上下文&#xff1a;运行一个进程所需要的所有资源。 b.上下文切换&#xff1a;替换原有内容&#xff0c;从访问进程A的所有资源切换到访问进程B的所有资源&#xff0c;是一个耗时操作。 c.为了提高系统性能&#xff0c;引入了一…

HCIP | 实验一

实验内容 配置 1.合理规划IP地址&#xff0c;启用OSPF单区域 R1 R2 R3 R4 R5 R6 2.R1-R2之间启用PPP的pap单向认证 R1 R2 3.R2-R3之间启用PPP的chap双向认证 R2 R3 4.R3-R5-R6之间使用MGRE&#xff0c;R3为hub端&#xff0c;R5&#xff0c;R6为spoke端&#xff0c;要求MGRE…

DS1302实时时钟(51单片机)

一、DS1302时钟 1.DS1302时钟介绍 2.芯片使用 使用芯片时首先要通过数据手册知道芯片功能&#xff0c;根据芯片功能应用。 3.实现DS1302功能 通过对配置寄存器使用DS1302的读写功能 二、实现DS1302读写 1.模块化编程框架 首先对DS1302端口重新定义&#xff08;换端口名字…

汽车电子推拉力测试机测试流程的详细步骤

在现代汽车技术迅猛发展的今天&#xff0c;汽车电子产品的可靠性已成为确保车辆性能和乘客安全的关键因素。标准下的键合线剪切试验&#xff0c;作为评估这些产品中关键连接点强度的一项测试&#xff0c;扮演着至关重要的角色。本文旨在深入探讨这一测试的重要性、实施流程及其…

Java学习Day20

Vue学习 nodejs的安装与环境配置 1.直接去官网下载合适版本的nodejs( https://nodejs.org/zh-cn/download/prebuilt-installer) 2.解压下载的安装包&#xff0c;将文件路径配置到系统变量的path中&#xff0c;然后确认后退出。可以使用终端来查看安装的nodejs版本。使用winR…

智能合约的未来:解析Web3在智能合约领域的创新

随着区块链技术的不断发展&#xff0c;智能合约已成为Web3生态系统中的核心组成部分。智能合约通过在区块链上自动执行合约条款&#xff0c;推动了去中心化应用&#xff08;DApp&#xff09;的广泛应用。它们的核心优势在于去中心化、透明和不可篡改&#xff0c;这使得合同执行…

uniapp切换同一个子组件时,钩子函数只进了一次

给子组件添加不同的 “key” 值&#xff0c;当 key 值改变时&#xff0c;Vue 会认为这是一个不同的组件&#xff0c;并重新创建它 props: ["L1Id"],// 方式1: 使用keycomputed: {// 切换子组件时,发现created、mounted等钩子函数只会进一次,或者用 keykey(){this.ref…

RAG私域问答场景超级详细方案(第一期方案)[1]:工业级别构建私域问答(知识处理、知识召回排序、搜索问答模块)

RAG私域问答场景整体夏详细方案(第一期方案):工业级别构建私域问答(知识处理、知识召回排序、搜索问答模块) 大模型性能的跳阶式增长给文本摘要、信息检索、信息抽取、语义问答等自然语言处理任务带来了卓越的性能提升。同时,LangChain 作为一种基于 LLM 的框架,能够快速…

【autoware】安装ros2 密匙gpg报错,443连接失败

443连接问题解决方法&#xff1a; 访问该网站 https://ping.chinaz.com 输入raw.githubusercontent.com可以得到解析出来的IP sudo vim /etc/hosts

Unity射击游戏开发教程:(31)制造一定追踪行为的敌人

在本文中,我们将介绍如何在两种敌人行为之间切换。本文是前两篇文章的延续,分别介绍了敌人躲避玩家射击以及敌人不断旋转并向玩家射击的情况。我只是介绍如何在这两种行为之间进行转换。 这种新的敌人行为的目标: 当不开火时,敌人可以躲避玩家的射击。射击时,敌人无法躲避…

lvs实战项目-dr模式实现

一、环境准备 主机名IP地址router eth0&#xff1a;172.25.254.100 eth1&#xff1a;192.168.0.100 clienteth0&#xff1a;172.25.254.200lvseth1&#xff1a;192.168.0.50web1web2 1、client配置 [rootclient ~]# cat /etc/NetworkManager/system-connections/eth0.nmconne…

使用FFmpeg实现摄像头RTMP实时推流

在当今的数字时代,视频直播已成为连接人与人之间的重要桥梁,广泛应用于在线教育、远程会议、娱乐直播等多个领域。随着技术的不断进步,人们对于直播的实时性、稳定性和高质量需求日益增加。为了实现高效的视频直播,选择合适的工具和协议至关重要。 RTMP(Real-Time Messagi…

Kotlin OpenCV 视频分析和对象跟踪60 MIL 对象跟踪

Kotlin OpenCV 视频分析和对象跟踪60 MIL 对象跟踪 1 OpenCV 对象跟踪算法2 Kotlin 引入依赖3 OpenCV 下载4 Kotlin OpenCV MIL 对象跟踪 1 OpenCV 对象跟踪算法 算法算法特点1 BOOSTING Tracker基于 AdaBoost 算法。适合于简单的对象跟踪任务。算法较老&#xff0c;在复杂场景…