动态设置复选框的步骤
初始化一个QTreeView 的界面,并设置相关的model
// 在ui中新建两个QTreeView 命名为 addedView,notAddView
//初始化QTreeView 界面
ui->setupUi(this);
ui->addedView->header()->hide();//表头隐藏
ui->notAddView->header()->hide();
//设置model
QStandardItemModel m_addedModel, m_notAddModel;
ui->addedView->setModel(&m_addedModel);
ui->notAddView->setModel(&m_notAddModel);
从数据库或其他地方获取相关数据:QSet<QString> addPeople,QSet<QString> notAddPeople
其中addPeople展示在addedView界面上,notAddPeople展示在notAddView界面上
if(!addPeople.empty())
{
m_addedModel.clear();
//如果addPeople(群已有成员)存在,则显示在界面上
if(!addPeople.empty())
{
int i=0;
QSet<QString>::iterator iter;
for(iter = addPeople.begin(); iter != addPeople.end(); iter++)
{
QStandardItem* pTem = new QStandardItem; // 新建项
pTem->setText(*iter); // 设置显示的名称
pTem->setCheckable(true); // 设置为复选框
m_addedModel.appendRow(pTem); // 把新建项插入到模型中
}
}
}
复选框如下图所示
功能:右边(未添加成员界面)选中复选框,点击添加,被选中的人会移到左边(已有成员)
将按钮和槽函数绑定:
connect(ui->pushButtonAdd, SIGNAL(clicked()), this, SLOT(slot_pushButtonAdd_clicked()));
槽函数思路
- QStandardItemModel
资料:函数介绍,TableView、QStandardItemModel、QItemSelectionModel
暂且将该函数理解为管理二位数据的类,我们通过ui->addedView->setModel(&m_addedModel);
将视图view和QStandardItemModel 绑定到一起。这样就可以通过QStandardItemModel 来管理显示在视图上的数据了
选中的数据,通过QStandardItemModel 来获取:
首先遍历QStandardItemModel 所有数据,查看哪个复选框被选中了checkState() == Qt::Checked
如果选中了,就新建一个QStandardItem,加入到m_addedModel模型中
代码如下:
QStringList vecIndexs;
for (int i = 0; i < m_notAddModel.rowCount(); i++) //遍历每一行
{
if (m_notAddModel.itemFromIndex(m_notAddModel.index(i, 0))->checkState() == Qt::Checked) //获取每一行的第一列,我只用了一列
{
QStandardItem* pItemEx = new QStandardItem(m_notAddModel.itemFromIndex(m_notAddModel.index(i, 0))->text());
pItemEx->setCheckable(true);
m_addedModel.appendRow(pItemEx);
}
else
{
vecIndexs.push_back(m_notAddModel.itemFromIndex(m_notAddModel.index(i, 0))->text());
}
}
m_notAddModel.clear();
for (size_t i = 0; i < vecIndexs.size(); i++)
{
QStandardItem* pItemEx = new QStandardItem(vecIndexs[i]);
pItemEx->setCheckable(true);
m_notAddModel.appendRow(pItemEx);
}
以上是解决:点击按钮,处理复选框的内容。
如果要解决点击复选框,处理复选框,比如点击父节点,全选子节点。
参考: Qt树形控件QTreeView使用2——复选框的设置
通过QStandardItemModel设置的项目,任何改变都会触发void QStandardItemModel::itemChanged(QStandardItem * item)信号
关联项目属性改变的信号和槽
connect ( model ,&QStandardItemModel::itemChanged , this ,&Widget::treeItemChanged );
void Widget : : treeItemChanged ( QStandardItem * item )
{
if ( item == nullptr )
return ;
if ( item - > isCheckable ())
{
//如果条目是存在复选框的,那么就进行下面的操作
Qt : : CheckState state = item - > checkState (); //获取当前的选择状态
if ( item - > isTristate ())
{
//如果条目是三态的,说明可以对子目录进行全选和全不选的设置
if ( state != Qt : : PartiallyChecked )
{
//当前是选中状态,需要对其子项目进行全选
treeItem_checkAllChild ( item , state == Qt : : Checked ? true : false );
}
}
else
{
//说明是两态的,两态会对父级的三态有影响
//判断兄弟节点的情况
treeItem_CheckChildChanged ( item );
}
}
}
这里的逻辑是:点击复选框就会触发 QStandardItemModel::itemChanged 信号,查看当前项的状态,对它进行操作。
和上一个事件对比:点击按钮,需要遍历所有项目QStandardItem,一个个查看是否选中(不知道有没有更好的方法)
问题:没有搞清楚 QItemSelectionModel干吗用的?
我弄混了的概念
QTreeView使用总结5,选中信号处理
Qt 学习之路:视图选择 (QItemSelectionModel)
Qt模型/视图框架(一)
QT MVC的概念
Qt Model/View(模型/视图)结构(无师自通)
模型-视图 编程
模型
所有的基于项数据的数据模型(Model)都是基于 QAbstractltemModel 类的,这个类定义了视图组件和代理存取数据的接口。数据无需存储在数据模型里,数据可以是其他类、文件、数据库或任何数据源。
QStringListModel 用来保存一列QString项。
QStandardItemModel 管理更复杂是树形数据结构,每一个条目都可以保存任意数据。
QFileSystemModel 提供了本地文件系统的文件和目录信息。
QSqlQueryModel, QSqlTableModel, 和 QSqlRelationalTableModel 通过模型/视图的约定规则来访问数据库。
目前用到的是 QStandardItemModel
添加数据
往表格添加数据:
QStandardItemModel tableModel(4, 4);
for (int row = 0; row < 4; ++row){
for (int column = 0; column < 4; ++column) {
QStandardItem *item = new QStandardItem(QString("%0,%1").arg(row).arg(column));
tableModel.setItem(row, column, item);
}
}
QTableView tableView;
tableView.setModel( & tableModel );
添加角色
QStandarItemModel *m_model = new QStandarItemModel ;
QStandardItem *item = new QStandardItem;
item->setData(QVariant(getVariantList(info)), Qt::DisplayRole);
item->setData(QVariant(iconSize()), Qt::SizeHintRole);
m_model->appendRow(item);
获取角色
QString name=item->data(Qt::SizeHintRole);
其中QStandardItem初始化 QStandardItem(Qstring a) 界面会显示a字符串
获取数据
在视图上设置模型之后,通常需要对用户操作做出反应,例如单击项目。由于QAbstractItemView提供基于QModelIndex的信号和函数,您需要一种方法来获得与给定QModelIndex对应的q标准化,反之亦然。itemFromIndex()和indexFromItem()提供了这个映射。itemFromIndex()的典型应用包括获取项目目前的索引视图,并获取项对应于一个索引由QAbstractItemView信号,如QAbstractItemView:点击()。首先在你的类中连接视图的符号
QTreeView *treeView = new QTreeView(this);
treeView->setModel(myStandardItemModel);
connect(treeView, SIGNAL(clicked(QModelIndex)),this, SLOT(clicked(QModelIndex)));
当您收到信号时,您在给定的模型索引上调用itemFromIndex(),以获得指向该项目的指针:
void MyWidget::clicked(const QModelIndex &index)
{
QStandardItem *item = myStandardItemModel->itemFromIndex(index);
}
相反,当您希望调用以索引为参数的模型/视图函数时,您必须获得项目的QModelIndex。您可以通过使用model的indexFromItem()函数来获得索引,也可以通过调用q标准化tem::index()来获得该索引:
treeView->scrollTo(item->index());
返过的错误
m_addedModel.itemFromIndex(m_addedModel.index(i, 0))->data().toString()
当时 m_addedModel.index(i, 0)并没有设置 data,即,
QStandardItem* pItemEx = new QStandardItem(vecIndexs[i]);
pItemEx->setData(strDatas.at(i));//这一步没有
所以那一行没有获取到数据
视图
视图用于显示模型中的数据
槽函数
Q_SIGNALS:
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected);
void currentChanged(const QModelIndex ¤t, const QModelIndex &previous);
void currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous);
void currentColumnChanged(const QModelIndex ¤t, const QModelIndex &previous);
void modelChanged(QAbstractItemModel *model);
例子:
//a.h
void SlotModelItemClickedShowBaseInfo(const QModelIndex ¤t, const QModelIndex &previous);
//a.cpp
connect(ui->treeView->selectionModel(), SIGNAL(currentRowChanged(const QModelIndex &, const QModelIndex &)), this, SLOT(SlotModelItemClickedShowBaseInfo(const QModelIndex &, const QModelIndex &)));
void a::SlotModelItemClickedShowBaseInfo(const QModelIndex ¤t, const QModelIndex &previous) {
QStandardItem* item = m_model.itemFromIndex(current);
if (item)
{
QString modelName = item->text();
ui->label->setText(modelName);
}
}