作者前言
🎂 ✨✨✨✨✨✨🍧🍧🍧🍧🍧🍧🍧🎂
🎂 作者介绍: 🎂🎂
🎂 🎉🎉🎉🎉🎉🎉🎉 🎂
🎂作者id:老秦包你会, 🎂
简单介绍:🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂🎂
喜欢学习C语言、C++和python等编程语言,是一位爱分享的博主,有兴趣的小可爱可以来互讨 🎂🎂🎂🎂🎂🎂🎂🎂
🎂个人主页::小小页面🎂
🎂gitee页面:秦大大🎂
🎂🎂🎂🎂🎂🎂🎂🎂
🎂 一个爱分享的小博主 欢迎小可爱们前来借鉴🎂
多元素控件
- **作者前言**
- 简单介绍
- List Widget
- Table Widget
- Treewidget
- QTreeWidgetItem
简单介绍
Qt 中提供的多元素控件有:
QListWidget
• QListView
• QTableWidget
• QTableView
• QTreeWidget
• QTreeView
简单的将其分为 列表(QListWidget、 QListView) ,表格(QTableWidget、QTableView)以及树(QTreeWidget、QTreeview)
widget和view的区别
以 QTableWidget 和 QTableView 为例.
• QTableView 是基于 MVC 设计的控件. QTableView ⾃⾝不持有数据. 使⽤ QTableView 的
时候需要⽤⼾创建⼀个 Model 对象 (⽐如 QStandardModel ), 并且把 Model 和
QTableView 关联起来. 后续修改 Model 中的数据就会影响 QTableView 的显⽰; 修改
QTableView 的显⽰也会影响到 Model 中的数据(双向绑定).
• QTableWidget 则是 QTableView 的⼦类, 对 Model 进⾏了封装. 不需要⽤⼾⼿动创建
Model 对象, 直接就可以往 QTableWidget 中添加数据了
如图:
MVC的介绍:
MVC 拆解成如下:
model (数据)、 view(视图界面)、controller(控制器,用于数据和视图的流程 ,简称媒介)
这里的view只是负责了视图的界面,不负责数据的存储和传输以及交互,如果使用view,需要程序员自己去实现model和controller这部分,
所以说widget就是基于view实现了model和controller这部分
好比我们需要买一台电脑, 方法1是自己买零件自己组装view就好比电脑的零件, 方法2就是直接买一台已经组装好的电脑,
List Widget
属性如下:
信号函数
下面写一个列表, 可以添加和删除内容的listwidget
代码如下:
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//创建一个列表QListWidget* list = new QListWidget(this);// 创建一个单行输入QLineEdit * line = new QLineEdit(this);line->setPlaceholderText("输入要添加的内容");line->move(list->x()+list->width()+200, 0);//添加按钮QPushButton *addButton = new QPushButton("添加", this);ButtonPostion(addButton, line->x(), line->y()+line->height()+20);//删除按钮QPushButton *deleteButton = new QPushButton("删除", this);ButtonPostion(deleteButton, addButton->x(), addButton->y()+addButton->height()+20);connect(addButton, &QPushButton::clicked, this, [=](){list ->addItem(new QListWidgetItem(line->text(),list));qDebug()<< list->count();qDebug()<< "添加的元素为:" << line->text();line->setText("");});connect(deleteButton, &QPushButton::clicked, this, [=](){QListWidgetItem * ret = nullptr;if(list->currentItem()){ret = list->takeItem(list->currentRow());}else if(list->count()!=0)ret = list ->takeItem(list->count()-1);qDebug()<< list->count();if(ret)qDebug()<< "删除的元素为:" << ret->text();});
}
void Widget::ButtonPostion(QPushButton *button, int x, int y) const
{button->move(x,y);
}
效果如下:
如果我们要写一个listview的代码,上面的代码是可以更改的,但是我们更改会比较困难,因为view只是一个显示的界面, 不能完成数据的计算,添加的内容和删除的内容,就需要我们一个个的去写代码,去计算, 使用listwidget就省略这些步骤,
Table Widget
使⽤ QTableWidget 表⽰⼀个表格控件,⼀个表格中包含若⼲⾏, 每⼀⾏⼜包含若⼲列.表格中的每个单元格, 是⼀个 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)
下面我们写一个代码,用来控制TableWidget的增删改查
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);//创建一个表格sheet = new QTableWidget(this);sheet->setFixedSize(300,600);//创建四个lineEditrowline = CreateLineEdit(sheet->x()+sheet->width()+200, sheet->y(), "输入行数");columnline = CreateLineEdit(rowline->x()+rowline->width()+200,rowline->y(), "输入列数");Verticalheader = CreateLineEdit(rowline->x(),rowline->y()+ rowline->width()+200, "输入行头");Horizontalheader = CreateLineEdit(Verticalheader->x()+Verticalheader->width()+200,Verticalheader->y(), "输入列头");//创建增加行按钮addRowButton = CreatePushButton(rowline->x()+rowline->width(), rowline->y()+rowline->height()+50, "添加行", &Widget::addRowSlot);//创建删除行按钮deleteRoeButton = CreatePushButton(addRowButton->x()+addRowButton->width()+50, addRowButton->y(), "删除行",&Widget::deleteRowSlot);//创建添加列按钮addColumnButton = CreatePushButton(addRowButton->x(), addRowButton->y()+addRowButton->height()+50, "添加列", &Widget::addColumnSlot);//创建删除列按钮deleteColumnButton = CreatePushButton(addColumnButton->x()+addColumnButton->width()+50, addColumnButton->y(), "删除列",&Widget::deleteColumnSlot);//添加内容addValueButton = CreatePushButton(addColumnButton->x(), addColumnButton->y()+addColumnButton->height()+50, "添加内容",&Widget::addValue);//删除内容deleteValueButton = CreatePushButton(addValueButton->x()+addValueButton->width()+50, addValueButton->y(), "删除内容",&Widget::deleteValue);//添加列头addHorizontalheaderButton = CreatePushButton(Horizontalheader->x(), Horizontalheader->y()+ Horizontalheader->height()+50, "增加列头",&Widget::addHorizontalValue);//添加行头addVerticalheaderButton = CreatePushButton(Verticalheader->x(), Verticalheader->y()+Verticalheader->height()+50, "增加行头",&Widget::addVetticalValue);// qDebug()<< rowline->x() << rowline->width() << addButton->pos();//设置选中单元格的信号和槽connect(sheet, &QTableWidget::cellClicked, this, [=](int row, int column){rowline->setText(QString::number(row+1));columnline->setText(QString::number(column+1));});}Widget::~Widget()
{delete ui;
}QLineEdit *Widget::CreateLineEdit(int x, int y, QString value)
{QLineEdit *rowline = new QLineEdit(this);rowline->move(x, y);rowline->setPlaceholderText(value);return rowline;
}QPushButton *Widget::CreatePushButton(int x, int y, QString value, void (Widget::*funtion)() ,int width, int heigth)
{QPushButton *addButton = new QPushButton(value, this);addButton->setFixedSize(100,30);addButton->move(x,y);connect(addButton,&QPushButton::clicked, this,funtion);return addButton;
}void Widget::addRowSlot()
{qDebug()<< "addRowSlot";//获取当前的选择的行,如果没有就在后面插入if(sheet->currentRow()< 0)//为选择要判断, 一种是行为空,一种是没空{sheet->insertRow(sheet->rowCount());}else{sheet->insertRow(sheet->currentRow());}qDebug()<< sheet->rowCount();
}void Widget::deleteRowSlot()
{qDebug()<< "deleteRowSlot" ;if(sheet->currentRow()>= 0)sheet->removeRow(sheet->currentRow());elsesheet->removeRow(sheet->rowCount()-1);//}void Widget::addColumnSlot()
{qDebug()<< "deleteRowSlot";//获取当前的选择的列,如果没有就在后面插入if(sheet->currentColumn()< 0){sheet->insertColumn(sheet->columnCount());}else{sheet->insertColumn(sheet->currentColumn());}
}void Widget::deleteColumnSlot()
{qDebug()<< "deleteColumnSlot";if(sheet->currentColumn()>= 0)sheet->removeColumn(sheet->currentColumn());elsesheet->removeColumn(sheet->columnCount()-1);//}void Widget::addValue()
{qDebug()<< "addValue";if(sheet->rowCount() >=rowline->text().toInt()&& sheet->columnCount()>= columnline->text().toInt())sheet->setItem(rowline->text().toInt()-1, columnline->text().toInt()-1, new QTableWidgetItem("111"));}void Widget::deleteValue()
{qDebug()<< "deleteValue";if(rowline->text().isEmpty()&&columnline->text().isEmpty())return;if(sheet->rowCount() >=rowline->text().toInt()&& sheet->columnCount()>= columnline->text().toInt())if(sheet->item(rowline->text().toInt()-1, columnline->text().toInt()-1))sheet->item(rowline->text().toInt()-1, columnline->text().toInt()-1)->setText("");}void Widget::addHorizontalValue()
{if(columnline->text().isEmpty())return;sheet->setHorizontalHeaderItem(columnline->text().toInt()-1,new QTableWidgetItem (Horizontalheader->text()));qDebug()<< "addHorizontalValue" << Horizontalheader->text();
}void Widget::addVetticalValue()
{if(rowline->text().isEmpty())return;sheet->setVerticalHeaderItem(rowline->text().toInt()-1,new QTableWidgetItem (Verticalheader->text()));qDebug()<< "addVetticalValue";
}
效果图:
一般情况下,我们是要通过读取文件或者网络获取数据的,不会傻乎乎的去手动添加,所以的我们可以去找一个Excel表格来进行内容的读取进行操作,这里的话就不演示了
Treewidget
使⽤ QTreeWidget 表⽰⼀个树形控件. ⾥⾯的每个元素, 都是⼀个 QTreeWidgetItem , 每个
QTreeWidgetItem 可以包含多个⽂本和图标, 每个⽂本/图标为⼀个 列
可以给 QTreeWidget 设置顶层节点(顶层节点可以有多个), 然后再给顶层节点添加⼦节点, 从⽽构成树形结构.
属性如下:
信号函数如下:
currentItemChanged(QTreeWidgetItem*
current, QTreeWidgetItem* old) 切换选中元素时触发
itemClicked(QTreeWidgetItem* item, int col) 点击元素时触发
itemDoubleClicked(QTreeWidgetItem* item, int col)双击元素时触发
itemEntered(QTreeWidgetItem* item, int col) ⿏标进⼊时触发
itemExpanded(QTreeWidgetItem* item) 元素被展开时触发
itemCollapsend(QTreeWidgetItem* item) 元素被折叠时触发
QTreeWidgetItem
这个是treewidget的节点对象类型, 和前面的listwidget的listwidhetItem以及tablewidget的tablewidgetitem是一样的情况,也有属于自己的函数, 下面列举一下,
addChild(QTreeWidgetItem* child) 新增⼦节点
childCount() ⼦节点的个数
child(int index) 获取指定下标的⼦节点. 返回 QTreeWidgetItem*
takeChild(int index) 删除对应下标的⼦节点
removeChild(QTreeWidgetItem*child) 删除对应的⼦节点
parent() 获取该元素的⽗节点
下面我们采用图形化的方式创建一个简单的界面, 然后在界面上进行操作, 进行顶点和子节点的创建和删除
ui文件:
代码如下:
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);
}Widget::~Widget()
{delete ui;
}void Widget::on_pushButton_clicked()
{QString value= ui->lineEdit->text();QStringList heade(value);ui->treeWidget->addTopLevelItem(new QTreeWidgetItem(heade));ui->lineEdit->setText("");}void Widget::on_pushButton_2_clicked()
{QString value= ui->lineEdit->text();QStringList heade(value);//获取当前的节点ui->treeWidget->currentItem()->addChild(new QTreeWidgetItem(heade));
}void Widget::on_pushButton_3_clicked()
{//获取当前的节点,并返回当前顶点在所有顶点的下标QTreeWidgetItem * curren = ui->treeWidget->currentItem();if(curren!= nullptr){int index = ui->treeWidget->indexOfTopLevelItem(curren);ui->treeWidget->takeTopLevelItem(index);}}void Widget::on_pushButton_4_clicked()
{//需要判断当前节点是否是顶点, 如果不是直接删除, 如果是删除顶点//获取当前的节点QTreeWidgetItem * curren = ui->treeWidget->currentItem();QTreeWidgetItem * parent = nullptr;if(curren)parent = curren->parent();if(parent == nullptr)on_pushButton_3_clicked();else{parent->removeChild(ui->treeWidget->currentItem());}}
效果如下:
可以看出,这个效果出编译完成出来, 是有一个根节点的,跟我们认识的不太一样,
这里的顶层节点不是根节点,而是根节点的孩子节点,如果觉得根节点的内容不好看,可以使用headerlabel函数去更改