Russian Qt Forum
Мая 04, 2025, 17:51 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: работа с QTableView  (Прочитано 12887 раз)
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.04 секунд. Запросов: 23.