Russian Qt Forum

Qt => Вопросы новичков => Тема начата: Pixel от Август 08, 2013, 15:04



Название: работа с QTableView
Отправлено: 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);
то запись видна. Вопос - как добавлять новые записи в модель?


Название: Re: работа с QTableView
Отправлено: mutineer от Август 08, 2013, 15:09
есть такие методы как
beginInsertRows()
endInsertRows()

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


Название: Re: работа с QTableView
Отправлено: Pixel от Август 08, 2013, 15:23
насколько я понял в процессе мучений, QAbstractItemModel не работает с моими данными, а делает их копию. Следовательно изменяя исходные данные я не меняю данные, хранящиеся внутри QAbstractItemModel. Решил проблему, передавая в QAbstractItemModel ссылку на мои данные. Как я мог не заметить такую глупость))


Название: Re: работа с QTableView
Отправлено: Pixel от Август 08, 2013, 15:43
И снова ничего не получается(( решение оказалось рабочим, только если добавлять элементы в той же функции где создается сама модель. Добавляю элементы по сигналу от другого класса и ничего не происходит. мистика о_О Похоже вопрос остается актуальным. Как заставить QTableView обновляться?


Название: Re: работа с QTableView
Отправлено: Bepec от Август 08, 2013, 15:55
есть такие методы как
beginInsertRows()
endInsertRows()

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


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


Название: Re: работа с QTableView
Отправлено: Bepec от Август 08, 2013, 16:22
У вас видимо серьёзное заболевание глаз или очень очень плохой монитор.
есть такие методы как
beginInsertRows()
endInsertRows()

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

PS и приводите код, если хотите чтобы вам что-то сказали, кроме "цитата - смотри вверху".


Название: Re: работа с QTableView
Отправлено: Pixel от Август 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);
замеряю. Получаю огромные задержки. Что не так?


Название: Re: работа с QTableView
Отправлено: mutineer от Август 08, 2013, 16:34
А ты уверен что задержки не в
Код
C++ (Qt)
game = new BaseGame;
 
?


Название: Re: работа с QTableView
Отправлено: mutineer от Август 08, 2013, 16:34
вот эту операцию:
Код:
tmGames->insertRow(gameList.size()-1);
замеряю. Получаю огромные задержки. Что не так?

А что этот метод внутри себя делает?


Название: Re: работа с QTableView
Отправлено: Pixel от Август 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 со своей моделью, но теперь оказывается она лагает точно также.


Название: Re: работа с QTableView
Отправлено: Bepec от Август 08, 2013, 16:51
Судя по вашему описание и непонятным обрывкам кода, думаю что:

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

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

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

PS QTableView при нормальной модели не тормозит.


Название: Re: работа с QTableView
Отправлено: Pixel от Август 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();
}


Название: Re: работа с QTableView
Отправлено: Pixel от Август 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();


Название: Re: работа с QTableView
Отправлено: gil9red от Август 08, 2013, 20:32
проблему решил. Если кому интересно, то все дело было в генерации моделью виджета сигналов (уш незнаю каких).
Скорее всего где то произошла бесконечная рекурсия с сигналами и слотами :)


Название: Re: работа с QTableView
Отправлено: Bepec от Август 08, 2013, 21:12
Да нет, скорее всего он добавляет записи по одной :D На каждую генерится сигнал :D

В принципе ТС тот ещё фрукт. В начале желал View в конце грит всё решено, Widget работает :D Не люблю это :D


Название: Re: работа с QTableView
Отправлено: Pixel от Август 08, 2013, 21:52
Bepec, разъясните пожалуйста как так добавить их сразу все? код приведен выше. Что поправить?
В начале желал View в конце грит всё решено, Widget работает
а так же там сказано, что отказался я от него по причине лагов, которые, как выяснилось позже, присутствуют у любой модели, как следствие и при использовании View.


Название: Re: работа с QTableView
Отправлено: Bepec от Август 08, 2013, 22:12
Ну начнём - с самого начала вы неправы - модели не одинаковы :P
Лагов в tableView ровно столько, насколько вы их реализуете в модели.

Widget тем и славится, что он "быстр" на мелких порциях. Что нибудь посерьёзнее - view.

Почему я не люблю такое - потому что название темы одно, в конце скажем так решения нет и присутствует неверная информация.

А почему никто вам не написал как сделать модель - потому что тем на форуме именно по моделям - целый раздел. Где всё обсосано. Имеется даже мануал.


Название: Re: работа с QTableView
Отправлено: Pixel от Август 08, 2013, 22:21
ссылочку можно на мануал? нашел только раздел вопросов


Название: Re: работа с QTableView
Отправлено: Bepec от Август 08, 2013, 23:03
Кхм. Тут я ошибся. Не на сайте, но на вашем компьютере есть :) В ассистенте.

Ну или же вот к примеру http://www.doc.crossplatform.ru/qt/4.7.x/html-qt/model-view-programming.html