`
qimo601
  • 浏览: 3444018 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

QAbstractTableModel中的data()到底执行几遍???

    博客分类:
  • Qt
阅读更多

有一个问题:QAbstractTableModel中的data()函数到底执行几遍???

 

 

发现问题的过程

 1、一个普通的继承 QAbstractTableModel 的类

 

 

class CurrencyModel : public QAbstractTableModel  
{  
public:  
    CurrencyModel(QObject *parent = 0);  
  
    void setCurrencyMap(const QMap<QString, double> &map);  
    int rowCount(const QModelIndex &parent) const;  
    int columnCount(const QModelIndex &parent) const;  
    QVariant data(const QModelIndex &index, int role) const;  
    QVariant headerData(int section, Qt::Orientation orientation,  
                        int role) const;  
  
private:  
    QString currencyAt(int offset) const;  
  
    QMap<QString, double> currencyMap;  
};  

 

 

 2、其中的重载的data()函数如下:

 

//返回一个项的任意角色的值,这个项被指定为QModelIndex
QVariant MoReconQueue::data(const QModelIndex &index, int role) const
{
	qDebug() <<"role:"<< role<< "index : " << index.row() << index.column();
    //模型索引无效,返回空值
    if (!index.isValid())
        return QVariant();
    //对其角色
    if (role == Qt::TextAlignmentRole)
    {
        return int(Qt::AlignRight | Qt::AlignVCenter);
    }
    //显示角色
    else if (role == Qt::DisplayRole)
    {
		
        return reconQueueAt(index.row(),index.column());

    }
	
    //返回空值
    return QVariant();
}
 

 

3、测试结果:

发现data()执行了3次遍历,每次遍历都执行每一行每一项的七个角色的赋值。

 

 

role: 6 index :  0 0

role: 7 index :  0 0

role: 9 index :  0 0

role: 10 index :  0 0

role: 1 index :  0 0

role: 0 index :  0 0

role: 8 index :  0 0 

 

 

 

 

我就纳闷了,执行一次遍历就够了,为啥要执行三遍呢。

 

Qt项数据角色如下:

 

enum Qt::ItemDataRole

Each item in the model has a set of data elements associated with it, each with its own role. The roles are used by the view to indicate to the model which type of data it needs. Custom models should return data in these types.

The general purpose roles (and the associated types) are:

Constant Value Description
Qt::DisplayRole 0 The key data to be rendered in the form of text. (QString)
Qt::DecorationRole 1 The data to be rendered as a decoration in the form of an icon. (QColorQIcon or QPixmap)
Qt::EditRole 2 The data in a form suitable for editing in an editor. (QString)
Qt::ToolTipRole 3 The data displayed in the item's tooltip. (QString)
Qt::StatusTipRole 4 The data displayed in the status bar. (QString)
Qt::WhatsThisRole 5 The data displayed for the item in "What's This?" mode. (QString)
Qt::SizeHintRole 13 The size hint for the item that will be supplied to views. (QSize)

Roles describing appearance and meta data (with associated types):

Constant Value Description
Qt::FontRole 6 The font used for items rendered with the default delegate. (QFont)
Qt::TextAlignmentRole 7 The alignment of the text for items rendered with the default delegate. (Qt::AlignmentFlag)
Qt::BackgroundRole 8 The background brush used for items rendered with the default delegate. (QBrush)
Qt::BackgroundColorRole 8 This role is obsolete. Use BackgroundRole instead.
Qt::ForegroundRole 9 The foreground brush (text color, typically) used for items rendered with the default delegate. (QBrush)
Qt::TextColorRole 9 This role is obsolete. Use ForegroundRole instead.
Qt::CheckStateRole 10 This role is used to obtain the checked state of an item. (Qt::CheckState)

Accessibility roles (with associated types):

Constant Value Description
Qt::AccessibleTextRole 11 The text to be used by accessibility extensions and plugins, such as screen readers. (QString)
Qt::AccessibleDescriptionRole 12 A description of the item for accessibility purposes. (QString)

User roles:

Constant Value Description
Qt::UserRole 32 The first role that can be used for application-specific purposes.

 

问题分析

 

 

1、经调试跟踪,Qt中的qtableview.h里面进行调用我们自定义的Modle


其中paint函数负责调用data()函数,我也很闷为啥绿色代码会遍历3次呢???那个Rects到底是什么值呢。。。其中的原理,我暂时还没搞明白。如果有知道的朋友,可以留言告诉我。谢谢

 

 

/*!

    Paints the table on receipt of the given paint event \a event.

*/

void QTableView::paintEvent(QPaintEvent *event)

{

    Q_D(QTableView);

    // setup temp variables for the painting

    QStyleOptionViewItemV4 option = d->viewOptionsV4();

    const QPoint offset = d->scrollDelayOffset;

    const bool showGrid = d->showGrid;

    const int gridSize = showGrid ? 1 : 0;

    const int gridHint = style()->styleHint(QStyle::SH_Table_GridLineColor, &option, this);

    const QColor gridColor = static_cast<QRgb>(gridHint);

    const QPen gridPen = QPen(gridColor, 0, d->gridStyle);

    const QHeaderView *verticalHeader = d->verticalHeader;

    const QHeaderView *horizontalHeader = d->horizontalHeader;

    const QStyle::State state = option.state;

    const bool alternate = d->alternatingColors;

    const bool rightToLeft = isRightToLeft();

 

    QPainter painter(d->viewport);

 

    // if there's nothing to do, clear the area and return

    if (horizontalHeader->count() == 0 || verticalHeader->count() == 0 || !d->itemDelegate)

        return;

 

    uint x = horizontalHeader->length() - horizontalHeader->offset() - (rightToLeft ? 0 : 1);

    uint y = verticalHeader->length() - verticalHeader->offset() - 1;

 

    const QRegion region = event->region().translated(offset);

    const QVector<QRect> rects = region.rects();

 

    //firstVisualRow is the visual index of the first visible row.  lastVisualRow is the visual index of the last visible Row.

    //same goes for ...VisualColumn

    int firstVisualRow = qMax(verticalHeader->visualIndexAt(0),0);

    int lastVisualRow = verticalHeader->visualIndexAt(verticalHeader->viewport()->height());

    if (lastVisualRow == -1)

        lastVisualRow = d->model->rowCount(d->root) - 1;

 

    int firstVisualColumn = horizontalHeader->visualIndexAt(0);

    int lastVisualColumn = horizontalHeader->visualIndexAt(horizontalHeader->viewport()->width());

    if (rightToLeft)

        qSwap(firstVisualColumn, lastVisualColumn);

    if (firstVisualColumn == -1)

        firstVisualColumn = 0;

    if (lastVisualColumn == -1)

        lastVisualColumn = horizontalHeader->count() - 1;

 

    QBitArray drawn((lastVisualRow - firstVisualRow + 1) * (lastVisualColumn - firstVisualColumn + 1));

 

    if (d->hasSpans()) {

        d->drawAndClipSpans(region, &painter, option, &drawn,

                             firstVisualRow, lastVisualRow, firstVisualColumn, lastVisualColumn);

    }

 

    for (int i = 0; i < rects.size(); ++i) {

        QRect dirtyArea = rects.at(i);

        dirtyArea.setBottom(qMin(dirtyArea.bottom(), int(y)));

        if (rightToLeft) {

            dirtyArea.setLeft(qMax(dirtyArea.left(), d->viewport->width() - int(x)));

        } else {

            dirtyArea.setRight(qMin(dirtyArea.right(), int(x)));

        }

 

        // get the horizontal start and end visual sections

        int left = horizontalHeader->visualIndexAt(dirtyArea.left());

        int right = horizontalHeader->visualIndexAt(dirtyArea.right());

        if (rightToLeft)

            qSwap(left, right);

        if (left == -1) left = 0;

        if (right == -1) right = horizontalHeader->count() - 1;

 

        // get the vertical start and end visual sections and if alternate color

        int bottom = verticalHeader->visualIndexAt(dirtyArea.bottom());

        if (bottom == -1) bottom = verticalHeader->count() - 1;

        int top = 0;

        bool alternateBase = false;

        if (alternate && verticalHeader->sectionsHidden()) {

            uint verticalOffset = verticalHeader->offset();

            int row = verticalHeader->logicalIndex(top);

            for (int y = 0;

                 ((uint)(y += verticalHeader->sectionSize(top)) <= verticalOffset) && (top < bottom);

                 ++top) {

                row = verticalHeader->logicalIndex(top);

                if (alternate && !verticalHeader->isSectionHidden(row))

                    alternateBase = !alternateBase;

            }

        } else {

            top = verticalHeader->visualIndexAt(dirtyArea.top());

            alternateBase = (top & 1) && alternate;

        }

        if (top == -1 || top > bottom)

            continue;

 

        // Paint each row item

        for (int visualRowIndex = top; visualRowIndex <= bottom; ++visualRowIndex) {

            int row = verticalHeader->logicalIndex(visualRowIndex);

            if (verticalHeader->isSectionHidden(row))

                continue;

            int rowY = rowViewportPosition(row);

            rowY += offset.y();

            int rowh = rowHeight(row) - gridSize;

 

            // Paint each column item

            for (int visualColumnIndex = left; visualColumnIndex <= right; ++visualColumnIndex) {

                int currentBit = (visualRowIndex - firstVisualRow) * (lastVisualColumn - firstVisualColumn + 1)

                        + visualColumnIndex - firstVisualColumn;

 

                if (currentBit < 0 || currentBit >= drawn.size() || drawn.testBit(currentBit))

                    continue;

                drawn.setBit(currentBit);

 

                int col = horizontalHeader->logicalIndex(visualColumnIndex);

                if (horizontalHeader->isSectionHidden(col))

                    continue;

                int colp = columnViewportPosition(col);

                colp += offset.x();

                int colw = columnWidth(col) - gridSize;

 

                const QModelIndex index = d->model->index(row, col, d->root);

                if (index.isValid()) {

                    option.rect = QRect(colp + (showGrid && rightToLeft ? 1 : 0), rowY, colw, rowh);

                    if (alternate) {

                        if (alternateBase)

                            option.features |= QStyleOptionViewItemV2::Alternate;

                        else

                            option.features &= ~QStyleOptionViewItemV2::Alternate;

                    }

                    d->drawCell(&painter, option, index);

                }

            }

            alternateBase = !alternateBase && alternate;

        }

 

        if (showGrid) {

            // Find the bottom right (the last rows/columns might be hidden)

            while (verticalHeader->isSectionHidden(verticalHeader->logicalIndex(bottom))) --bottom;

            QPen old = painter.pen();

            painter.setPen(gridPen);

            // Paint each row

            for (int visualIndex = top; visualIndex <= bottom; ++visualIndex) {

                int row = verticalHeader->logicalIndex(visualIndex);

                if (verticalHeader->isSectionHidden(row))

                    continue;

                int rowY = rowViewportPosition(row);

                rowY += offset.y();

                int rowh = rowHeight(row) - gridSize;

                painter.drawLine(dirtyArea.left(), rowY + rowh, dirtyArea.right(), rowY + rowh);

            }

 

            // Paint each column

            for (int h = left; h <= right; ++h) {

                int col = horizontalHeader->logicalIndex(h);

                if (horizontalHeader->isSectionHidden(col))

                    continue;

                int colp = columnViewportPosition(col);

                colp += offset.x();

                if (!rightToLeft)

                    colp +=  columnWidth(col) - gridSize;

                painter.drawLine(colp, dirtyArea.top(), colp, dirtyArea.bottom());

            }

 

            //draw the top & left grid lines if the headers are not visible.

            //We do update this line when subsequent scroll happen (see scrollContentsBy)

            if (horizontalHeader->isHidden() && verticalScrollMode() == ScrollPerItem)

                painter.drawLine(dirtyArea.left(), 0, dirtyArea.right(), 0);

            if (verticalHeader->isHidden() && horizontalScrollMode() == ScrollPerItem)

                painter.drawLine(0, dirtyArea.top(), 0, dirtyArea.bottom());

            painter.setPen(old);

        }

}

 

 

 

0
0
分享到:
评论

相关推荐

    QML_QAbstractTableModel.zip

    在本文中,我们将深入探讨如何在Qt的QML环境中利用C++的`QAbstractTableModel`作为数据模型,以便在QML界面中展示数据。`QAbstractTableModel`是Qt的一个核心组件,它允许我们自定义数据模型,从而可以方便地与QML...

    QT-QabstractTableModel模型、重写sort方法排序

    QT中的`QAbstractTableModel`是Qt库中一个非常重要的组件,它是`QAbstractItemModel`的一个子类,专为表格视图(如`QTableView`)设计,用于处理表格数据模型。在Qt的模型/视图框架中,模型是数据的提供者,视图则...

    自己开发的集成qabstracttablemodel的派生类,

    2. **自定义数据访问**:通过重载`QAbstractTableModel`的方法,如`data()`, `headerData()`, `insertRows()`, `removeRows()`等,可以控制如何获取、设置和管理数据。 3. **扩展功能**:可能需要添加额外的功能,...

    自定义TableMode模型,继承QAbstractTableModel,自定义数据模型 TestQTableView3.zip

    自定义TableMode模型,继承QAbstractTableModel,自定义数据模型 TestQTableView3.,使用QVector作为模型的底层数据结构存储数据,其内存占用与QList相当,尾部追加插入耗时与QList相当,但头部插入比QList耗时较多

    自定义TableMode模型,继承QAbstractTableModel,自定义数据模型,可加载1千万行大数据

    自定义TableMode模型,继承QAbstractTableModel,自定义数据模型。 可以很快得加载完1000万行大数据,并且占用的内存也不大,可加载1千万行大数. 使用QVector作为模型的底层数据结构存储数据,其内存占用与QList相当...

    Qt_Sqlite_database.rar_Qt数据库_sqlite QT_sqlite查询

    // 重写QAbstractTableModel的方法,如rowCount, columnCount, data, headerData等 private: // 存储数据的相关成员变量 }; ``` ```cpp // tablemodel.cpp TableModel::TableModel(QObject *parent) : ...

    电子表格 QT C++ 程序 源代码

    在创建电子表格程序时,你需要实现QAbstractTableModel的几个关键方法,如data()、headerData()、rowCount()和columnCount()等。data()用于获取单元格的数据,headerData()用于设置或获取列头和行头的信息,rowCount...

    Python-MongoDB-示例:Python,Qt,PySide2,MongoDB,PyMongo,QTreeView和QAbstractTableModel的实时工作示例应用程序

    Python-MongoDB-示例Python,Qt,PySide2,MongoDB,PyMongo,QTableView,QAbstractTableModel的实时工作示例应用程序提供了此应用程序的完整视频教程请订阅我的YouTube频道来吸引我。这是什么应用程序? 这是一个...

    spreadsheet

    8. **数据模型(QAbstractTableModel)**:对于更复杂的需求,你可以使用QAbstractTableModel类作为基础,创建自己的数据模型,这将允许你更好地控制数据的存储和显示方式。 9. **用户交互**:QTableWidget支持多种...

    CustomsizedModel.rar

    在这个项目中,我们可能会创建一个继承自QAbstractTableModel的自定义模型类,以便存储和操作文本数据。 自定义模型意味着我们需要重写几个关键的虚函数,例如`rowCount()`, `columnCount()`, `data()`, 和 `header...

    QTableView同时显示自定义Checkbox和文件图标

    在模型类中,我们需要添加额外的列来存储Checkbox的状态,并实现相应的数据访问接口,如`data()`、`flags()`和`setData()`。 ```cpp class CustomTableModel : public QAbstractTableModel { Q_OBJECT public: /...

    TestQTableView.zip

    创建一个自定义的模型类,继承自QAbstractTableModel,然后在`data()`方法中实现数据的获取和处理。接着,创建一个自定义委托,继承自QStyledItemDelegate,覆盖`paint()`和`editorEvent()`方法以实现特定的视觉...

    MVC_QTableView_Model_Delegate.rar

    在本文中,我们将深入探讨如何使用QT框架中的关键组件,如`QTableView`、`QAbstractTableModel`和`QStyledItemDelegate`,以及如何在这些组件中集成`QCheckBox`和可点击按钮,来实现一个功能丰富的MVC(模型-视图-...

    QT连接数据库,并将串口中的数据并存储到mysql数据库中在线显示

    在本文中,我们将深入探讨如何使用QT框架连接到MySQL数据库,并实时处理来自串口的数据,将其存储到数据库中,同时实现在线显示。这是一项在物联网(IoT)项目或实时数据监控应用中常见的任务。 首先,让我们了解基础...

    QTableViewExample.zip

    QAbstractTableModel的接口如data()、headerData()、rowCount()和columnCount()等方法,是实现数据模型的关键。 "mainwindow.cpp"和"mainwindow.h"则是主窗口类,通常包含对整个应用程序界面的管理,包括创建和设置...

    qt model QtableView

    `MyCustomTableModel`需要继承自`QAbstractTableModel`,并实现其必要的接口,如`rowCount()`, `columnCount()`, `data()`, `headerData()`等,以便填充数据和响应视图的请求。 接下来,我们关注如何将数据加载到...

    tableView数据库的显示及自定义样式

    在`CSqlTableModel::data`中,你需要根据列的索引返回相应的值,这可能包括数据库中的字段值、显示的文本,甚至是自定义格式化后的信息。例如,你可能会根据数据类型进行转换,将整数或日期格式化为可读的字符串。 ...

    Qt中的tablewidget 通过分页方式加载大量数据

    - 创建一个继承自QAbstractTableModel的自定义模型类,实现必要的方法如rowCount()、columnCount()、data()等,以满足数据的读取需求。 - 在模型类中维护一个当前页的数据列表,以及总行数和每页行数的信息。 - ...

    QT实现可拖拽排序的表格

    在QT中,QTableView是用于显示二维表格数据的主要控件,通常与QAbstractTableModel或QStandardItemModel一起使用。 要实现拖拽排序,我们需要对QTableView进行自定义。首先,我们需要重载QTableView的...

    QTableView-MODEL VIEW 自定义模型实现.rar

    首先,我们需要了解Qt中的三种基本模型:QStandardItemModel、QAbstractListModel和QAbstractTableModel。QStandardItemModel是最简单的模型,适用于小型和简单的数据集;QAbstractListModel和QAbstractTableModel是...

Global site tag (gtag.js) - Google Analytics