Russian Qt Forum
Ноябрь 26, 2024, 14:38 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: работа с QTableView  (Прочитано 12522 раз)
Pixel
Гость
« : Август 08, 2013, 15:04 »

Начал работать с QTableWidget, но он при добавлении новых элементов неприемлемо медленно работает (примерно 300 элементов в секунду). Решил взяться за QTableView со своей моделью. Унаследовался от QAbstractTableModel, переопределил rowCount, columnCount, data. Возник вопрос, каким образом QAbstractTableModel обновляется? Как он понимает что данные изменились? Вот есть у меня массив (QVector) из моих данных, хранится он внутри моей модели. Получается вот такой код:
Код:
    QVector<someclass*> vector;
    QTableView *view = new QTableView(this);
    TableModel *model = new TableModel(vector, this);
    view->setModel(model);
    someclass *data = new someclass;
    vector.append(data);
Но в таблице ничего нет. А вот если сделать так:
Код:
    QVector<someclass*> vector;
    QTableView *view = new QTableView(this);
    view->setModel(model);
    someclass *data = new someclass;
    vector.append(data);
    TableModel *model = new TableModel(vector, this);
то запись видна. Вопос - как добавлять новые записи в модель?
« Последнее редактирование: Август 08, 2013, 15:08 от Pixel » Записан
mutineer
Гость
« Ответ #1 : Август 08, 2013, 15:09 »

есть такие методы как
beginInsertRows()
endInsertRows()

и прочие, которые уведомляют View о том, что в модели что-то поменялось. Используй их
Записан
Pixel
Гость
« Ответ #2 : Август 08, 2013, 15:23 »

насколько я понял в процессе мучений, QAbstractItemModel не работает с моими данными, а делает их копию. Следовательно изменяя исходные данные я не меняю данные, хранящиеся внутри QAbstractItemModel. Решил проблему, передавая в QAbstractItemModel ссылку на мои данные. Как я мог не заметить такую глупость))
« Последнее редактирование: Август 08, 2013, 15:41 от Pixel » Записан
Pixel
Гость
« Ответ #3 : Август 08, 2013, 15:43 »

И снова ничего не получается(( решение оказалось рабочим, только если добавлять элементы в той же функции где создается сама модель. Добавляю элементы по сигналу от другого класса и ничего не происходит. мистика о_О Похоже вопрос остается актуальным. Как заставить QTableView обновляться?
Записан
Bepec
Гость
« Ответ #4 : Август 08, 2013, 15:55 »

есть такие методы как
beginInsertRows()
endInsertRows()

и прочие, которые уведомляют View о том, что в модели что-то поменялось. Используй их
Записан
Pixel
Гость
« Ответ #5 : Август 08, 2013, 16:06 »

Код:
    vector.append(game);
    model->insertRow(vector.size()-1);
вот таким образом заработало (переопределил insertRows). 392 элемента с 1 столбиком за 133 мс, что немногим меньше чем QTableWidget. это вообще нормально? неужели в Qt добавление элементов в таблицу НАСТОЛЬКО не оптимизированно. Никак нельзя избежать таких лагов?
Записан
Bepec
Гость
« Ответ #6 : Август 08, 2013, 16:22 »

У вас видимо серьёзное заболевание глаз или очень очень плохой монитор.
есть такие методы как
beginInsertRows()
endInsertRows()

и прочие, которые уведомляют View о том, что в модели что-то поменялось. Используй их

PS и приводите код, если хотите чтобы вам что-то сказали, кроме "цитата - смотри вверху".
Записан
Pixel
Гость
« Ответ #7 : Август 08, 2013, 16:30 »

вот пожалуйста:
Код:
bool TableModel::insertRows(int row, int count,
                            const QModelIndex & parent = QModelIndex())
{
    beginInsertRows(parent, row, row+count-1);
    BaseGame *game;
    for (int row = 0; row < count; ++row) {
        game = new BaseGame;
        gameList->append(game);
    }

    endInsertRows();
    return true;
}
вот эту операцию:
Код:
tmGames->insertRow(gameList.size()-1);
замеряю. Получаю огромные задержки. Что не так?
« Последнее редактирование: Август 08, 2013, 16:33 от Pixel » Записан
mutineer
Гость
« Ответ #8 : Август 08, 2013, 16:34 »

А ты уверен что задержки не в
Код
C++ (Qt)
game = new BaseGame;
 
?
Записан
mutineer
Гость
« Ответ #9 : Август 08, 2013, 16:34 »

вот эту операцию:
Код:
tmGames->insertRow(gameList.size()-1);
замеряю. Получаю огромные задержки. Что не так?

А что этот метод внутри себя делает?
Записан
Pixel
Гость
« Ответ #10 : Август 08, 2013, 16:41 »

Цитировать
А что этот метод внутри себя делает?
вызывает insertRows для одного элемента.

Код:
bool TableModel::insertRows(int row, int count,
                            const QModelIndex & parent = QModelIndex())
{
    beginInsertRows(parent, row, row+count-1);
    endInsertRows();
    return true;
}

Код:
tmGames->insertRows(0, 1, tmGames->index(0, 0));

такой же эффект.
P.S. встретил уже множество тем про лаги QTableWidget. Мол он не предназначен для больших объемов информации. Рекомендуют использовать QTableView со своей моделью, но теперь оказывается она лагает точно также.
« Последнее редактирование: Август 08, 2013, 16:46 от Pixel » Записан
Bepec
Гость
« Ответ #11 : Август 08, 2013, 16:51 »

Судя по вашему описание и непонятным обрывкам кода, думаю что:

1) вы переопределяете один метод, а вызываете другой. WTF?

2) вы добавляете запись одну за одной, мб стоит подумать и добавлять много записей за один раз?

3) вы создаёте динамически в insertRows какой то класс - это плохо Улыбающийся

PS QTableView при нормальной модели не тормозит.
Записан
Pixel
Гость
« Ответ #12 : Август 08, 2013, 18:57 »

1) тот же самый метод insertRows.
2) никакой разницы.
3) в последнем посте ничего не создается

Перешел обратно на QTableWidget, так как с ним проще работать, а лагает он точно также. Заметил одну странную вещь. Если сделать так:
Код:
    twGames = new QTableWidget(500, 1, this);
    QTableWidgetItem *item;

    QTime time;
    time.start();
    for(int i=0; i<500; i++){
        item = new QTableWidgetItem("lol");
        twGames->setItem(i, 0, item);
    }
    qDebug() << "done!" << time.elapsed();

таймер выдает 3 мс. а если создать виджет в одной фунции (в моем случае конструктор моего класса):
Код:
twGames = new QTableWidget(500, 1, this);
, а вот это в другой (в моем случае слот этого же класса):
Код:
    QTime time;
    time.start();
    QTableWidgetItem *item;
    for(int i=0; i<500; i++){
        item = new QTableWidgetItem("lol");
        twGames->setItem(i, 0, item);
    }
    qDebug() << "done!" << time.elapsed();
покажет ~250. Я почти уверен, что разобравшись почему так, можно будет избавится от лагов. Вот цельный код, если не нравятся обрывки:
описание класса:
Код:
class FormBase: public QMainWindow
{
Q_OBJECT

private:
    QTableWidget *twGames;

public:
    explicit FormBase();
    void updateGames();
};
реализация:
Код:
FormBase::FormBase()
{
    setMinimumSize(600, 500);

    twGames = new QTableWidget(500, 1, this);
    QTableWidgetItem *item;
    setCentralWidget(twGames);

далее все комментируется для теста слота

    QTime time;
    time.start();

   for(int i=0; i<500; i++){
        item = new QTableWidgetItem("lol");
        twGames->setItem(i, 0, item);
    }
    qDebug() << "done!" << time.elapsed();
}

void FormBase::updateGames()
{
    QTime time;
    time.start();
    QTableWidgetItem *item;
    for(int i=0; i<500; i++){
        item = new QTableWidgetItem("lol");
        twGames->setItem(i, 0, item);
    }
    
    qDebug() << "done!" << time.elapsed();
}
« Последнее редактирование: Август 08, 2013, 19:06 от Pixel » Записан
Pixel
Гость
« Ответ #13 : Август 08, 2013, 19:11 »

проблему решил. Если кому интересно, то все дело было в генерации моделью виджета сигналов (уш незнаю каких). Вот так никаких лагов:
Код:
    QTime time;
    time.start();
    twGames->model()->blockSignals(1);
    QTableWidgetItem *item;
    for(int i=0; i<500; i++){
        item = new QTableWidgetItem("lol");
        twGames->setItem(i, 0, item);
    }
    twGames->model()->blockSignals(0);
    twGames->reset();
    qDebug() << "done!" << time.elapsed();
Записан
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #14 : Август 08, 2013, 20:32 »

проблему решил. Если кому интересно, то все дело было в генерации моделью виджета сигналов (уш незнаю каких).
Скорее всего где то произошла бесконечная рекурсия с сигналами и слотами Улыбающийся
« Последнее редактирование: Август 08, 2013, 20:50 от gil9red » Записан

Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.119 секунд. Запросов: 23.