crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

2 страниц V   1 2 >  
Ответить в данную темуНачать новую тему
> QAbstractListModel
gpepsi
  опции профиля:
сообщение 3.5.2011, 10:54
Сообщение #1


Студент
*

Группа: Участник
Сообщений: 73
Регистрация: 31.3.2010
Пользователь №: 1582

Спасибо сказали: 0 раз(а)




Репутация:   0  


Нужна таблица с десятком колонок и многими сотнями строк.
Создал модель. Переопределил для нее
1. rowCount
2. columnCount
3. headerData
4. data

Далее довольно интенсивно добавляю записи.
После каждого добавления прокручиваю скрол и делаю модели reset.

После нескольких сотен записей приложение ложиться.
Хотя на экран влезает лишь пару десятков строк, но модель пытается получить данные для всех строк.
Нафига она это делает для невидимых строк и как заставить отрисовывать ее только видимые строки.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
wiz29
  опции профиля:
сообщение 3.5.2011, 11:31
Сообщение #2


Старейший участник
****

Группа: Участник
Сообщений: 600
Регистрация: 7.7.2010
Из: Санкт-Петербург
Пользователь №: 1866

Спасибо сказали: 94 раз(а)




Репутация:   12  


. напиши свою модель данных, раз не устраивает стандартная реализация QStringListModel (скорее всего ты ее используешь). Для этого нужно реализовать интерфейс QAbstractListModel унаследовавшись от QAbstractListModel. Если работа каких то виртуальных методов не устраивает, никто не запрещает реализацию этих методов переопределить...

Сообщение отредактировал wiz29 - 3.5.2011, 11:33
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
gpepsi
  опции профиля:
сообщение 3.5.2011, 14:47
Сообщение #3


Студент
*

Группа: Участник
Сообщений: 73
Регистрация: 31.3.2010
Пользователь №: 1582

Спасибо сказали: 0 раз(а)




Репутация:   0  


Цитата(wiz29 @ 3.5.2011, 12:31) *
. напиши свою модель данных, раз не устраивает стандартная реализация QStringListModel (скорее всего ты ее используешь). Для этого нужно реализовать интерфейс QAbstractListModel унаследовавшись от QAbstractListModel. Если работа каких то виртуальных методов не устраивает, никто не запрещает реализацию этих методов переопределить...


а что я и сделал :)

Цитата(gpepsi @ 3.5.2011, 11:54) *
Создал модель. Переопределил для нее
1. rowCount
2. columnCount
3. headerData
4. data
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
wiz29
  опции профиля:
сообщение 3.5.2011, 14:56
Сообщение #4


Старейший участник
****

Группа: Участник
Сообщений: 600
Регистрация: 7.7.2010
Из: Санкт-Петербург
Пользователь №: 1866

Спасибо сказали: 94 раз(а)




Репутация:   12  


Для твоего случая переопределить только те 4 метода значит мало (это базовые методы, которые достаточно переопределить, чтобы модель просто "ожила"), необходимо больше телодвижений, к сожалению, скорее всего, стандартные реализации тебе тут не помогут, придется руками переопределять реализацию тех методов, которые понижают производительность твоего приложения и ни как иначе.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
gpepsi
  опции профиля:
сообщение 3.5.2011, 17:29
Сообщение #5


Студент
*

Группа: Участник
Сообщений: 73
Регистрация: 31.3.2010
Пользователь №: 1582

Спасибо сказали: 0 раз(а)




Репутация:   0  


Цитата(wiz29 @ 3.5.2011, 15:56) *
Для твоего случая переопределить только те 4 метода значит мало (это базовые методы, которые достаточно переопределить, чтобы модель просто "ожила"), необходимо больше телодвижений, к сожалению, скорее всего, стандартные реализации тебе тут не помогут, придется руками переопределять реализацию тех методов, которые понижают производительность твоего приложения и ни как иначе.


так про то и вопрос был - что именно нужно еще сделать ?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 3.5.2011, 21:04
Сообщение #6


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(gpepsi @ 3.5.2011, 13:54) *
После каждого добавления прокручиваю скрол и делаю модели reset.
а зачем ресет?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
gpepsi
  опции профиля:
сообщение 4.5.2011, 7:37
Сообщение #7


Студент
*

Группа: Участник
Сообщений: 73
Регистрация: 31.3.2010
Пользователь №: 1582

Спасибо сказали: 0 раз(а)




Репутация:   0  


Цитата(Litkevich Yuriy @ 3.5.2011, 22:04) *
а зачем ресет?

а как еще обновить модель ?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
PAFOS
  опции профиля:
сообщение 6.5.2011, 8:13
Сообщение #8


Активный участник
***

Группа: Участник
Сообщений: 258
Регистрация: 27.12.2010
Из: Дмитров
Пользователь №: 2309

Спасибо сказали: 29 раз(а)




Репутация:   8  


Цитата
После каждого добавления прокручиваю скрол и делаю модели reset.


При добавлении записей (т.е. в методе virtual bool insertRows ( int row, int count, const QModelIndex & parent = QModelIndex() )) необходимо вызывать методы beginInsertRows() перед непосредственным добавлением строк и endInserRows() после него. В этом случае представление, показывающее твою модель обновит только новые строчки и не надо вызывать reset().
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
gpepsi
  опции профиля:
сообщение 6.5.2011, 11:53
Сообщение #9


Студент
*

Группа: Участник
Сообщений: 73
Регистрация: 31.3.2010
Пользователь №: 1582

Спасибо сказали: 0 раз(а)




Репутация:   0  


Цитата(PAFOS @ 6.5.2011, 9:13) *
При добавлении записей (т.е. в методе virtual bool insertRows ( int row, int count, const QModelIndex & parent = QModelIndex() )) необходимо вызывать методы beginInsertRows() перед непосредственным добавлением строк и endInserRows() после него. В этом случае представление, показывающее твою модель обновит только новые строчки и не надо вызывать reset().


накидал тестовый пример с использованием insertRows.
Можно увидеть как ложиться приложение.

Если раскомментировать assert в методе data, то можно увидеть, что он отработает, хотя первая строка не отображается.
Это и говорит о моем предположении, что QTreeView пытается вычитать всю модель, а не только те строки, которые отображаются.
Если данных много, то кирдык.

Получается, что куча ненужного кода, а работает так же как и обычный reset

main.cpp
#include <QtGui/QApplication>
#include "treeview.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    TreeView tree;
    tree.show();
    return app.exec();
}


treeview.h
#ifndef TREEVIEW_H
#define TREEVIEW_H

#include <QTreeView>

class Model : public QAbstractListModel{
private:
    typedef QMap<int, QString>    MapHeader;

    QStringList m_slist;
    MapHeader    m_header;

    virtual int rowCount        (const QModelIndex& index  = QModelIndex()) const;
    virtual int columnCount        (const QModelIndex& parent = QModelIndex()) const;
    virtual QVariant data        (const QModelIndex& index, int role) const;
    virtual QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
    virtual bool insertRows        (int row, int count, const QModelIndex& parent = QModelIndex());
    virtual bool setData        (const QModelIndex& index, const QVariant& data, int role = Qt::EditRole);

public :
    explicit Model(QObject* parent = 0);
    virtual ~Model() {}

    int addString(const QString& data);
};

class TreeView : public QTreeView {
    Q_OBJECT

public:
    explicit TreeView(QWidget *parent = 0);
    virtual ~TreeView() {}

private:
    Model m_model;
    virtual void timerEvent (QTimerEvent* event);
};
#endif // TREEVIEW_H


treeview.cpp
#include "treeview.h"
#include <QUuid>

Model::Model( QObject* parent /*= 0*/ )
{
    m_header[0] = tr("№");
    m_header[1] = tr("UUID");
}

int Model::rowCount( const QModelIndex& index /*= QModelIndex()*/ ) const
{
    return m_slist.size();
}

int Model::columnCount( const QModelIndex& parent /*= QModelIndex()*/ ) const
{
    return m_header.size();
}

QVariant Model::data( const QModelIndex& index, int role ) const
{
    if (!index.isValid()) return QVariant();
    const QString& uuid = m_slist[index.row()];

    //////////////////////////////////////////////////////////////////////////
//     if (m_slist.size() > 100)
//     {
//         _ASSERTE(index.row() != 1);
//     }
    //////////////////////////////////////////////////////////////////////////

    if (role == Qt::DisplayRole)
    {
        switch(index.column())
        {
            case 0 : return (index.row() + 1);
            case 1 : return uuid;
        }
    }
    return QVariant();
}

QVariant Model::headerData( int section, Qt::Orientation orientation, int role /*= Qt::DisplayRole*/ ) const
{
    return (role == Qt::DisplayRole) ? m_header[section] : QVariant();
}

bool Model::insertRows( int row, int count, const QModelIndex& parent /*= QModelIndex()*/ )
{
    beginInsertRows (parent, row, row + count);
    for (int i = 0; i < count; ++i)
    {
        m_slist.insert(row, QString());
    }
    endInsertRows ();
    return true;
}

bool Model::setData( const QModelIndex& index, const QVariant& data, int role /*= Qt::EditRole*/ )
{
    if (index.isValid() && (role == Qt::DisplayRole))
    {
        QString uuid = data.toString();
        m_slist[index.row()] = uuid;
        emit dataChanged (index, index);
        return true;
    }
    return false;
}

int Model::addString( const QString& data )
{
    int index = m_slist.size();
    insertRow(index);
    QModelIndex mindex = createIndex(index, 0);
    setData(mindex, QVariant::fromValue(data), Qt::DisplayRole);
    return m_slist.size();
}

TreeView::TreeView( QWidget *parent ) : QTreeView(parent), m_model(this)
{
    setModel(&m_model);
    if (startTimer(100) == 0)
    {
        QT_THROW("Error create timer");
    }    
}

void TreeView::timerEvent( QTimerEvent* event )
{
    QUuid uuid = QUuid::createUuid();
    int count = m_model.addString(uuid.toString());
    QModelIndex mindex = m_model.index(count - 1);
    scrollTo(mindex, QAbstractItemView::EnsureVisible);
}
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
PAFOS
  опции профиля:
сообщение 6.5.2011, 12:58
Сообщение #10


Активный участник
***

Группа: Участник
Сообщений: 258
Регистрация: 27.12.2010
Из: Дмитров
Пользователь №: 2309

Спасибо сказали: 29 раз(а)




Репутация:   8  


Возникает данная ересь именно при скролинге.
Если посмотреть внимательно, то когда приложение сваливается, значение переменной role в данном вызове равно 13, что означает Qt::SizeHintRole.
Если углубиться дальше, то поднявшись по стеку вызовов, попадем в итоге на int QTreeView::verticalOffset() const. В этом методе есть такой код:
        for (int i = 0; i < d->viewItems.count(); ++i) {
            if (i == verticalScrollBar()->value())
                return offset;
            offset += d->itemHeight(i);
        }


т.е. да, view шерстит всю модель на Qt::SizeHintRole.

Вот класс QTableView не определяет при каждом скролинге высоту каждого итема и все работает гуд.


Сообщение отредактировал PAFOS - 6.5.2011, 13:24
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

2 страниц V   1 2 >
Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 28.12.2024, 7:25