视频教程
https://www.bilibili.com/video/BV1FP4y1z75U/?vd_source=8be9e83424c2ed2c9b2a3ed1d01385e9
QItemSelectionModel
Qt的MVC结构支持多个View共享同一个model,包括该model的选中状态等。我们可以通过设置QItemSelectionModel,来更改View的选中效果和显示效果。我们创建一个Qt Application项目,在MainWindow的头文件中添加一个QTbaleView*
类型的成员 _table_view。然后在构造函数中为这个_table_view设置model
MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);QStandardItemModel * model = new QStandardItemModel(7,4,this);for(int row=0; row < 7; row++){for(int column = 0; column < 4; column++){QStandardItem * item = new QStandardItem(QString("%1").arg(row*4+column));model->setItem(row, column, item);}}_table_view = new QTableView;_table_view->setModel(model);setCentralWidget(_table_view);this->resize(800,800);
}
我们创建了一个QStandardItemModel对象,然后为其设置几个Item,最后将这个model设置到tableview中。
我们可以为TableView设置选择的项目,接下来继续在构造函数中补充
//获取视图的项目选择模型QItemSelectionModel * selection_model = _table_view->selectionModel();//定义左上角和右下角的索引QModelIndex topLeft;QModelIndex bottomRight;//根据上面两个索引选择项目//第1行1列topLeft = model->index(1,1,QModelIndex());//第5行2列bottomRight = model->index(5,2,QModelIndex());//设置选择区域QItemSelection selection(topLeft, bottomRight);//将选择的区域设置给选择模型, 设置 为选中状态selection_model->select(selection, QItemSelectionModel::Select);
我们从tableview中获取选择模型,然后从根节点下选择第1行1列作为左上索引,选择第5行2列作为右下索引。然后创建选择区域QItemSelection,最后将选择区域这只给选择模型。接下来为了我们为工具栏添加两个动作,为动作绑定两个槽函数,在MainWindow声明文件中添加两个函数的声明
public slots:void getCurrentItemData();void toggleSelection();
在构造函数中将动作和槽函数绑定起来
ui->mainToolBar->addAction(tr("当前项目"), this, &MainWindow::getCurrentItemData);ui->mainToolBar->addAction(tr("切换选择"), this, &MainWindow::toggleSelection);
实现这两个槽函数, getCurrentItemData获取当前条目的数据信息,toggleSelection实现切换选择的条目
void MainWindow::getCurrentItemData(){auto currentData = _table_view->selectionModel()->currentIndex().data().toString();qDebug() <<tr("当前项目的内容") << currentData;
}void MainWindow::toggleSelection(){//找到根节点下第0行0列的item的索引QModelIndex topLeft = _table_view->model()->index(0,0,QModelIndex());//获取根节点下最大的行号auto max_row = _table_view->model()->rowCount(QModelIndex());//获取根节点下最大的列号auto max_column = _table_view->model()->columnCount(QModelIndex());//根据列号和行号获取最右下角的item的索引QModelIndex bottomRight = _table_view->model()->index(max_row-1, max_column-1, QModelIndex());//设置选择区域QItemSelection curSelection(topLeft, bottomRight);_table_view->selectionModel()->select(curSelection, QItemSelectionModel::Toggle);
}
通过点击切换选择,可以实现选择区域的切换,因为我们设置选择的类型为Toggle,系统会将选中的变为取消选中,将取消选中的变为选中。
切换前
切换后
因为默认当前的条目是第1行1列,所以getCurrentItemData会打印他的信息。每一个model都有当前条目和选择条目两个属性。
捕获选择条目的变化
当我们点击鼠标选择一个条目时,当前条目就变为该条目,选择的条目也变为该条目。我们可以通过选择模型发出的selectionChanged信号,获取选择了那些条目的索引,以及取消选择了哪些条目的索引。我们可以通过currentChanged获取当前的条目索引以及变化之前的条目索引。现在MainWindow中添加两个槽函数的声明
public slots:void updateSelection(const QItemSelection& selected, const QItemSelection& deselected);void changeCurrent(const QModelIndex& current, const QModelIndex& previous);
两个槽函数的参数和信号的参数匹配。我们实现changeCurrent,当选择模型的当前索引变化时,打印变化前后的索引行号,列号。
void MainWindow::changeCurrent(const QModelIndex& current, const QModelIndex& previous){qDebug() << tr("move(%1, %2) to (%3, %4)").arg(previous.row()).arg(previous.column()).arg(current.row()).arg(current.column());
}
然后我们实现选择模型的选择条目变化时更新条目的数据
void MainWindow::updateSelection(const QItemSelection& selected, const QItemSelection& deselected){QModelIndex index;QModelIndexList list = selected.indexes();//为现在的选择项目设置值for(int i =0; i < list.size(); i++){QString text = QString("(%1, %2)").arg(list[i].row()).arg(list[i].column());_table_view->model()->setData(list[i], text);}list = deselected.indexes();foreach(index, list){_table_view->model()->setData(index,"");}
}
在MainWindow的构造函数中添加信号和槽函数的链接
//选择模型的选择条目更改后触发updateSelection函数connect(selection_model, &QItemSelectionModel::selectionChanged, this, &MainWindow::updateSelection);//选择模型的当前项目更改后,关联changeCurrent函数connect(selection_model, &QItemSelectionModel::currentChanged, this, &MainWindow::changeCurrent);
点击某个条目,其他条目的数据都变为空,这个条目被选中,内容修改为行列号
多个View共享模型
MVC结构最大的好处就是可以通过多个View共享同一个model,这个model的选中状态改变时,多个View的显示效果一致。
在构造函数中添加另一个QTableView
QTableView * tableView2;tableView2 = new QTableView();tableView2->setWindowTitle("tableView2");tableView2->resize(400,300);tableView2->setModel(model);tableView2->setSelectionModel(selection_model);tableView2->show();
可以看到两个View显示的选中状态是一致的
源码链接
源码链接
https://gitee.com/secondtonone1/qt-learning-notes