Метод QAbstractTableModel :: data вызывается слишком много раз - PullRequest
0 голосов
/ 13 декабря 2011

Мне нужен элемент управления графическим интерфейсом таблицы, который может быстро добавлять и отображать около 100 000 элементов.По этой причине необходим «виртуальный» табличный элемент управления, который загружает и показывает только видимые элементы.Я пробовал QTableView и QAbstractTableModel:

class MyModel : public QAbstractTableModel
{
public:
MyModel(QObject * parent, IDataSource* dataSource) 
    : QAbstractTableModel(parent), m_dataSource(dataSource) {}

int rowCount(const QModelIndex& parent = QModelIndex()) const
{
    return m_dataSource->rowCount();
}

int columnCount(const QModelIndex& parent = QModelIndex()) const
{
    return 3;
}

QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const
{
    if (role == Qt::DisplayRole)
    {
            return m_dataSource->cell(index.row(), index.column());
    }
    return QVariant();
}

bool addItem()
{
    beginInsertRows(QModelIndex(), rowCount(), rowCount());
    endInsertRows();
    return true;
}

private:
IDataSource* m_dataSource;
};

...

MyModel* model = new MyModel(this, this);
m_ui.tableView->setModel(model);
m_ui.tableView->show();

Проблема в том, что MyModel :: data () вызывается при добавлении новых элементов из видимой области.И это сильно замедляет работу.Это мой тестовый сценарий, чтобы быть более конкретным:

  1. Представление создается только с 5 элементами, которые могут быть видны одновременно.
  2. Я добавляю 20 элементов с помощью MyModel :: addItems.
  3. MyModel :: data вызывается для всех видимых элементов.
  4. MyModel :: data продолжает вызываться для видимых элементов (1 ... 5), когда элементы 6, 7, 9 ..Добавлено 20.

Я думал, что это может быть вызвано вертикальной полосой прокрутки, которая перерисовывается при добавлении новых элементов и, кажется, перерисовывает все QListView.Но после сокрытия вертикальной полосы прокрутки проблема осталась.Пожалуйста, предложите.

Ответы [ 2 ]

2 голосов
/ 16 декабря 2011

Я не выяснил, как предотвратить вызов метода endInsertRows, который вызовет дополнительные вызовы метода data ().Но вызов endInsertRows один раз для нескольких элементов решает проблему производительности.Поэтому я звоню:

beginInsertRows(QModelIndex(), rowCount(), rowCount() + 1000);
endInsertRows();

вместо того, чтобы звонить 1000 раз:

beginInsertRows(QModelIndex(), rowCount(), rowCount());
endInsertRows();
0 голосов
/ 13 декабря 2011

Какова асимптотическая сложность вашей реализации dataSource-> cell ()? data () действительно может вызываться много раз, даже больше, если вы, например, добавите QSortFilterProxyModel сверху для сортировки. Чтобы обеспечить производительность представлений элементов с большими объемами данных, для выполнения data () требуется только постоянное время.

...