QT MVC 中合并单元格处理

    技术2022-05-20  35

    QT中使用QTableView/QTableModel时合并单元格的处理

     

    扩展 QTableModel/QAbstractItemModel 在单元格属性中保存合并信息,我使用Qt::UserRole属性,使用QPoint保存合并的范围。

    扩展 QTableView,重载 reset() 方法,增加setSpans()函数处理合并操作

    void ReportTableView::reset() { clearSpans(); setSpans(); QTableView::reset(); } void ReportTableView::setSpans() { QAbstractItemModel* pModel = model(); if( !pModel ) { return; } int i, j; QModelIndex idx; QVariant spanInfo; QPoint spanRange; for(i=0; i < pModel->rowCount(); ++i) { for(j=0; j < pModel->columnCount(); ++j) { idx = pModel->index(i, j); if(idx.isValid()) { spanInfo = idx.data(Qt::UserRole); // get cell span info if(spanInfo.isValid() && spanInfo.canConvert<QPoint>()) { spanRange = spanInfo.toPoint(); setSpan(i, j, spanRange.x(), spanRange.y()); } } } } } 

     

    类似,可以实现根据单元格内容自动进行合并的TableView。

    bool checkRelevantCol(set<int> relevantCols, int cmpRow, int curRow, const QAbstractItemModel* model) { QModelIndex cmpA, curA; set<int>::iterator itA = relevantCols.begin(); for(; itA != relevantCols.end(); ++itA) { cmpA = model->index(cmpRow, *itA); curA = model->index(curRow, *itA); if( !(cmpA.isValid() && curA.isValid() && cmpA.data() == curA.data()) ) { return false; } } return true; } /* * @param column 需要根据内容自动合并的列 * @param relevantCols 合并是需要参考的列 */ void ReportTableView::setSpans(int column, set<int> &relevantCols) { QAbstractItemModel *pModel = model(); if( !pModel ) { return; } QModelIndex curIndex; QModelIndex cmpIndex; int maxSpanRow = 0; int i = column; { curIndex = pModel->index(0,i); maxSpanRow = 0; for( int j = 1; j < pModel->rowCount(); ++j ) { cmpIndex = pModel->index(j,i); if( cmpIndex.isValid() ) { if(!curIndex.isValid()) { curIndex = cmpIndex; } else if( cmpIndex.data() == curIndex.data() && checkRelevantCol(relevantCols, j, curIndex.row(), pModel) ) { maxSpanRow = j; } else { if(maxSpanRow != 0) { table->setSpan( curIndex.row(), curIndex.column(), maxSpanRow - curIndex.row() + 1, 1 ); } curIndex = cmpIndex; maxSpanRow = 0; } } else { if(maxSpanRow != 0 && curIndex.isValid()) { table->setSpan( curIndex.row(), curIndex.column(), maxSpanRow - curIndex.row() + 1, 1 ); } maxSpanRow = 0; curIndex = cmpIndex; } } if( maxSpanRow == cmpIndex.row() ) { table->setSpan( curIndex.row(), curIndex.column(), maxSpanRow - curIndex.row() + 1, 1 ); } } }

    因为要根据当前顺序遍历数据,如果数据量不大还好。


    最新回复(0)