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,系统会将选中的变为取消选中,将取消选中的变为选中。 切换前 https://cdn.llfc.club/1671529103099.jpg 切换后 https://cdn.llfc.club/1671529287147.jpg 因为默认当前的条目是第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);

点击某个条目,其他条目的数据都变为空,这个条目被选中,内容修改为行列号 https://cdn.llfc.club/1671530820828.jpg

多个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://cdn.llfc.club/1671531054879.jpg

源码链接

源码链接 https://gitee.com/secondtonone1/qt-learning-notes

results matching ""

    No results matching ""