Russian Qt Forum

Qt => Model-View (MV) => Тема начата: Larry от Март 23, 2016, 10:42



Название: [РЕШЕНО]Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 23, 2016, 10:42
Добрый день.
Все же QTableWidget не справился с работай и уже при 160 записях жутко тормозил, поэтому пришлось переходить на QTableView.
У меня есть QMap<int, struct> с данными, которые мне надо отображать...Вернее отображать не все, а некоторые по условию. Например, в первой и во второй колонке текст, а в остальных разные иконки при определенных условиях. Как мне это сделать?

структура имеет следующий вид:
Код:
struct status_t
{
    QDateTime datetime; // a datetime last point
    bool          state; // a state car in last point (move or stop)
    float         power; // a voltage network car in last point
    float         battery; // a voltage battery device in last point
    int            speed; // a speed car in last point
    QPointF     coord; // a coordinates last point
    int            sat; // a count sattelite in last point
    bool          communication; // a communication with car (active or inactive)
};

Спасибо.


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Igors от Март 23, 2016, 10:48
Все же QTableWidget не справился с работай и уже при 160 записях жутко тормозил, поэтому пришлось переходить на QTableView.
Может при 160 тысячах записей? А если все-таки при "просто 160" - значит что-то не так делаете


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 23, 2016, 11:16
Узнать бы что делаю не так, а так реально 162 записи и прокрутка срабатывает через пару секунд. У меня там вставляются в ячейки виджеты с текстом и иконками и обновляются данные с сервера где-то раз в 10 секунд. Если бы заработал этот вариант, то было бы очень хорошо, т.к. там уже все сделано, а так придется менять :).

Есть класс наследник от QTableWidget:

Код:
#ifndef QTABLECARS_H
    #define QTABLECARS_H
    //---------------------
    #include <QTableWidget>
    #include <QHeaderView>
    #include <QHBoxLayout>
    #include <QLabel>
    #include <QToolTip>
    #include <QDebug>
    #include "qstatuscars.h"
    #include "qstatusitem.h"
    //-----------------------------------
    class QTableCars: public QTableWidget
    {
        Q_OBJECT

        public:
            QTableCars(QWidget* parent = nullptr);
            ~QTableCars();

        public slots:
            void slotUpdateStatusCars(QStatusCars::statuses_t& statuses);

        signals:
            void updateItem(int, QPointF, const QString&);

        private:
            void createItems(QStatusCars::statuses_t& statuses);
            void createItem(int row, int id, QStatusCars::status_t& status);
            int  findItem(int id);
            void updateStatus(int row, int id, QStatusCars::status_t& status);
    };
#endif // QTABLECARS_H
Код:
#include "qtablecars.h"
//--------------------------------------
QTableCars::QTableCars(QWidget* parent):
    QTableWidget(parent)
{
    setSelectionBehavior(QAbstractItemView::SelectRows);
    setSelectionMode(QAbstractItemView::SingleSelection);
    setShowGrid(false);
    horizontalHeader()->hide();
    verticalHeader()->hide();

    setStyleSheet("QTableWidget::item { background-color: white; border: 1px solid #e0e0e0; }"
                  "QTableWidget::item:selected { background-color: #c0c0c0; }");
}
//-----------------------
QTableCars::~QTableCars()
{

}
//----------------------------------------------------------------------
void QTableCars::slotUpdateStatusCars(QStatusCars::statuses_t& statuses)
{
    if(this->rowCount() == 0)
    {
        createItems(statuses);
        return;
    }

    for(int key: statuses.keys())
    {
        int row = findItem(key);

        if(row != -1)
        {
            updateStatus(row, key, statuses[key]);
        }
        else
        {
            row = rowCount();
            insertRow(row);

            createItem(row, key, statuses[key]);
        }
    }

    resizeColumnsToContents();
    resizeRowsToContents();
}
//-------------------------------------------------------------
void QTableCars::createItems(QStatusCars::statuses_t& statuses)
{
    if(statuses.isEmpty())
        return;

    setRowCount(statuses.size());
    setColumnCount(6);

    int rowCount = 0;

    for(int id: statuses.keys())
    {
        createItem(rowCount, id, statuses[id]);

        rowCount++;
    }

    resizeColumnsToContents();
    resizeRowsToContents();
}
//-------------------------------------------------------------------------
void QTableCars::createItem(int row, int id, QStatusCars::status_t& status)
{
    QStatusItem* item_id            = new QStatusItem(QStatusItem::QTextRole);
    QStatusItem* item_speed         = new QStatusItem(QStatusItem::QTextRole);
    QStatusItem* item_state         = new QStatusItem;
    QStatusItem* item_battery       = new QStatusItem;
    QStatusItem* item_satellite     = new QStatusItem;
    QStatusItem* item_communication = new QStatusItem;

    setCellWidget(row, 0, item_id);
    setCellWidget(row, 1, item_speed);
    setCellWidget(row, 2, item_state);
    setCellWidget(row, 3, item_battery);
    setCellWidget(row, 4, item_satellite);
    setCellWidget(row, 5, item_communication);

    updateStatus(row, id, status);
}
//------------------------------
int QTableCars::findItem(int id)
{
    for(int row = 0; row < rowCount(); row++)
    {
        QStatusItem* wgt = qobject_cast<QStatusItem*>(cellWidget(row, 0));

        if(wgt && id == wgt->text().toInt())
            return row;
    }

    return -1;
}
//---------------------------------------------------------------------------
void QTableCars::updateStatus(int row, int id, QStatusCars::status_t& status)
{
    emit updateItem(id, status.coord, QString::number(status.speed));

    QStatusItem* item_id            = static_cast<QStatusItem*>(cellWidget(row, 0));
    QStatusItem* item_speed         = static_cast<QStatusItem*>(cellWidget(row, 1));
    QStatusItem* item_state         = static_cast<QStatusItem*>(cellWidget(row, 2));
    QStatusItem* item_battery       = static_cast<QStatusItem*>(cellWidget(row, 3));
    QStatusItem* item_satellite     = static_cast<QStatusItem*>(cellWidget(row, 4));
    QStatusItem* item_communication = static_cast<QStatusItem*>(cellWidget(row, 5));

    if(item_id)
    {
        item_id->setContent(QString::number(id));
        QString tooltip = "ID: " + QString::number(id) + "\n";
        tooltip += "Speed: " + QString::number(status.speed) + "km/h" + "\n";
        tooltip += "Fixed satellite: " + QString::number(status.sat) + "\n";
        tooltip += "Last position: " + QString::number(status.coord.y()) + ", " + QString::number(status.coord.x()) + "\n";
        tooltip += "Last point: " + status.datetime.toString("dd.MM.yyyy - hh:mm:ss");

        item_id->setToolTip(tooltip);
        item_id->setStyleSheet("background: white; color: black;");
    }
    else
        return;

    QString str;

    if(item_speed && status.speed > 0)
    {
        if(status.communication)
        {
            item_speed->setStyleSheet("color: green;");
            str = tr("Last state: movement");
        }
        else
        {
            item_speed->setStyleSheet("color: red;");
            str = tr("Last state: movement (no communication)");
        }

        item_speed->setContent(QString::number(status.speed) + "km/h");
    }
    else if(item_speed)
    {
        item_speed->setContent("");
        str = tr("Last state: stop");
    }

    if(status.state && item_state)
        item_state->setContent(":/icons/icons/move.png");
    else if(item_state)
        item_state->setContent(":/icons/icons/stop.png");

    item_state->setToolTip(str);
    item_state->setStyleSheet("background: white;");

    if(status.power < 10.0f && item_battery)
        item_battery->setContent(":/icons/icons/battery.png");
    else if(item_battery)
        item_battery->setContent("");

    if(status.sat == 0 && item_satellite)
    {
        item_satellite->setContent(":/icons/icons/satellite.png");
        str = tr("No satellites");
    }
    else if(item_satellite)
    {
        item_satellite->setContent("");
        str = tr("Fixed: ") + QString::number(status.sat) + tr(" satellites");
    }

    item_satellite->setToolTip(str);
    item_satellite->setStyleSheet("background: white;");

    if(!status.communication && item_communication)
    {
        item_communication->setContent(":/icons/icons/disconnected.png");
        str = tr("No connection\nLast point: ") + status.datetime.toString("dd.MM.yyyy - hh:mm:ss");
    }
    else if(item_communication)
    {
        item_communication->setContent("");
        str = tr("Last point: ") + status.datetime.toString("dd.MM.yyyy - hh:mm:ss");
    }

    item_communication->setToolTip(str);
    item_communication->setStyleSheet("background: white;");

    setRowHeight(row, item_state->width());
    setColumnWidth(0, item_id->width());
    setColumnWidth(1, item_speed->width());
    setColumnWidth(2, item_state->width());
    setColumnWidth(3, item_battery->width());
    setColumnWidth(4, item_satellite->width());
    setColumnWidth(5, item_communication->width());
}

И есть класс итема наследник от QWidget:
Код:
#ifndef QSTATUSITEM_H
    #define QSTATUSITEM_H
    //----------------
    #include <QWidget>
    #include <QLabel>
    #include <QHBoxLayout>
    #include <QHelpEvent>
    #include <QToolTip>
    #include <QDebug>
    //-------------------
    class QStatusTooltip;
    //-------------------------------
    class QStatusItem: public QWidget
    {
        Q_OBJECT

        public:
            enum Role{QIconRole = Qt::UserRole + 100, QTextRole};

        public:
            explicit QStatusItem(Role role = QIconRole, QWidget* parent = nullptr);
            ~QStatusItem();

            void    setContent(const QString& name);
            QSize   sizeHint() const;
            QString text() const;

        private:
            QLabel*         m_item;
            QHBoxLayout*    m_layout;
            Role            m_role;
            QStatusTooltip* m_tooltip;
    };
#endif // QSTATUSITEM_H

Код:
#include "qstatusitem.h"
//---------------------------------------------------
QStatusItem::QStatusItem(Role role, QWidget* parent):
    QWidget(parent),
    m_item(nullptr),
    m_layout(nullptr),
    m_role(role),
    m_tooltip(nullptr)
{
    m_item   = new QLabel(this);
    m_layout = new QHBoxLayout;

    m_layout->setContentsMargins(0, 0, 0, 0);
    m_layout->setMargin(0);
    m_layout->setSpacing(0);
    m_layout->addWidget(m_item);
    m_layout->setAlignment(Qt::AlignCenter);

    setLayout(m_layout);

    m_item->setStyleSheet("background: none");
}
//-------------------------
QStatusItem::~QStatusItem()
{
    if(m_item)
        delete m_item;

    if(m_layout)
        delete m_layout;
}
//-----------------------------------------------
void QStatusItem::setContent(const QString& name)
{
    QSize size_item;

    if(m_role == QIconRole)
    {
        m_item->setPixmap(QPixmap(name));

        const QPixmap* pixmap_item = m_item->pixmap();

        if(pixmap_item)
            size_item = pixmap_item->size();
        else
            size_item = QSize(0, 0);
    }
    else
    {
        QFont        font = m_item->font();
        QFontMetrics fm(font);

        size_item = QSize(fm.width(name)*1.2, fm.height()*1.2);

        m_item->setAlignment(Qt::AlignCenter);
        m_item->setText(name);
    }

    resize(size_item);
}
//---------------------------------
QSize QStatusItem::sizeHint() const
{
    return size();
}
//-------------------------------
QString QStatusItem::text() const
{
    return m_item->text();
}

Подскажите где может быть узкое место. Спасибо.


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Igors от Март 23, 2016, 11:23
Выложите виде компилируемого проекта (запакованного в zip)


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 23, 2016, 11:38
К сожалению не могу, т.к. там присутствуют данные для подключения к серверу с данными клиента. Тормоза происходят в этом методе:
Код:
void QTableCars::updateStatus(int row, int id, QStatusCars::status_t& status)
{
    emit updateItem(id, status.coord, QString::number(status.speed));

    QStatusItem* item_id            = static_cast<QStatusItem*>(cellWidget(row, 0));
    QStatusItem* item_speed         = static_cast<QStatusItem*>(cellWidget(row, 1));
    QStatusItem* item_state         = static_cast<QStatusItem*>(cellWidget(row, 2));
    QStatusItem* item_battery       = static_cast<QStatusItem*>(cellWidget(row, 3));
    QStatusItem* item_satellite     = static_cast<QStatusItem*>(cellWidget(row, 4));
    QStatusItem* item_communication = static_cast<QStatusItem*>(cellWidget(row, 5));

    if(item_id)
    {
        item_id->setContent(QString::number(id));
        QString tooltip = "ID: " + QString::number(id) + "\n";
        tooltip += "Speed: " + QString::number(status.speed) + "km/h" + "\n";
        tooltip += "Fixed satellite: " + QString::number(status.sat) + "\n";
        tooltip += "Last position: " + QString::number(status.coord.y()) + ", " + QString::number(status.coord.x()) + "\n";
        tooltip += "Last point: " + status.datetime.toString("dd.MM.yyyy - hh:mm:ss");

        item_id->setToolTip(tooltip);
        item_id->setStyleSheet("background: white; color: black;");
    }
    else
        return;

    QString str;

    if(item_speed && status.speed > 0)
    {
        if(status.communication)
        {
            item_speed->setStyleSheet("color: green;");
            str = tr("Last state: movement");
        }
        else
        {
            item_speed->setStyleSheet("color: red;");
            str = tr("Last state: movement (no communication)");
        }

        item_speed->setContent(QString::number(status.speed) + "km/h");
    }
    else if(item_speed)
    {
        item_speed->setContent("");
        str = tr("Last state: stop");
    }

    if(status.state && item_state)
        item_state->setContent(":/icons/icons/move.png");
    else if(item_state)
        item_state->setContent(":/icons/icons/stop.png");

    item_state->setToolTip(str);
    item_state->setStyleSheet("background: white;");

    if(status.power < 10.0f && item_battery)
        item_battery->setContent(":/icons/icons/battery.png");
    else if(item_battery)
        item_battery->setContent("");

    if(status.sat == 0 && item_satellite)
    {
        item_satellite->setContent(":/icons/icons/satellite.png");
        str = tr("No satellites");
    }
    else if(item_satellite)
    {
        item_satellite->setContent("");
        str = tr("Fixed: ") + QString::number(status.sat) + tr(" satellites");
    }

    item_satellite->setToolTip(str);
    item_satellite->setStyleSheet("background: white;");

    if(!status.communication && item_communication)
    {
        item_communication->setContent(":/icons/icons/disconnected.png");
        str = tr("No connection\nLast point: ") + status.datetime.toString("dd.MM.yyyy - hh:mm:ss");
    }
    else if(item_communication)
    {
        item_communication->setContent("");
        str = tr("Last point: ") + status.datetime.toString("dd.MM.yyyy - hh:mm:ss");
    }

    item_communication->setToolTip(str);
    item_communication->setStyleSheet("background: white;");

    setRowHeight(row, item_state->width());
    setColumnWidth(0, item_id->width());
    setColumnWidth(1, item_speed->width());
    setColumnWidth(2, item_state->width());
    setColumnWidth(3, item_battery->width());
    setColumnWidth(4, item_satellite->width());
    setColumnWidth(5, item_communication->width());
}


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 23, 2016, 11:47
Отключил вывод изображений, оставил только надписи на QLabel, работать стало быстрее, но все равно подтормаживает при прокрутке.


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Bepec от Март 23, 2016, 12:06
Ковырять куски кода, без цельной картины бессмысленно. Вот будет конкретика, тогда посмотрим :)


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 23, 2016, 12:11
Спасибо, а не подскажите как установить свою роль на колонку в QTableView?


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 23, 2016, 12:50
Что-то никак не въеду. Свою роль можно только через setData вставить? Но setData это для изменения данных при редактировании или я неправильно понимаю? Просто мне надо ввести несколько дополнительных ролей, чтобы брать данные и отрисовывать их как мне надо. Но как-то не въеду как добавить роль ячейке...Подскажите плиз...


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Bepec от Март 23, 2016, 12:59
добавить свою роль и её обработку нужно в модели. А вот уже изменять можно в setData.


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 23, 2016, 13:16
Так изначально как установить роль? Н-р, я добавил роли:
enum ModelRole
{
        StateRole = Qt::UserRole + 1,
        PowerRole
};

и как теперь эти роли назначить колонкам?


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 23, 2016, 17:54
Пытаюсь вставить пустую строку, но ничего не вставляется...Что может быть?
Код:
void QModelCars::addCar(int id, QStatusCars::status_t& status)
{
    if(m_statuses.keys().contains(id))
        return;

    int row = rowCount();
    insertRow(row);
}


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Bepec от Март 23, 2016, 18:14
Хз. Мы же не знаем что в insertRow происходит.
Нака пару вариантов:
1) всё добавляется, но view не дают сигналы о добавлении и он не обновляется.
2) ничего не добавляется, всё рушится на условии.
3) всё добавляется, испорчена система отображения данных.


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 23, 2016, 18:23
Все разобрался. Переопределил insertRows() и все создается.
Спасибо.


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 24, 2016, 17:03
Подскажите пожалуйста, где у меня проблемы. Во вложении минимальный компилируемый пример. Только данные одни и те же и обновляются по таймеру раз в 10 секунд. При работе QTableWidget тормоза начинались при 162 объектах. При работе с QTableView на 162 работает нормально, но при количестве объектов 2000 снова тормоза.
Спасибо.


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 25, 2016, 11:32
Засек время заполнения таблицы и получилось, что чтобы закинуть 1346 записей в таблицу требуется 287 секунд...надо уходить от QMap к другому контейнеру, чтобы выделять не по одной строке, а сразу необходимое количество строк, т.к. qmap не позволяет задать размер по умолчанию.


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: gil9red от Март 25, 2016, 11:40
А вы там processEvent не вызываете?


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 25, 2016, 11:49
нет. Я думаю пока переделать на qvector, чтобы мог резервировать или потом делать resize. А сейчас получается в цикле 2000 объектов по одному заносятся.


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Bepec от Март 25, 2016, 11:52
Что то там у вас не то. Запись 2к объектов не может занимать столько времени...
Надо будет на досуге посмотреть.


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 25, 2016, 11:56
Спасибо. Буду рад помощи, т.к. с моделями начал недавно работать, то возможно где-то косячу. Проверил парсинг данных от сервера - потолок 25 мс, а вот заполнение сплошной тормоз. Сейчас переделаю на qvector и отпишусь.


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Igors от Март 25, 2016, 12:19
Засек время заполнения таблицы и получилось, что чтобы закинуть 1346 записей в таблицу требуется 287 секунд...надо уходить от QMap к другому контейнеру, чтобы выделять не по одной строке, а сразу необходимое количество строк, т.к. qmap не позволяет задать размер по умолчанию.
Что же Вы так безбожно QMap::keys вызываете на каждый чих? Это удовольствие дорогое, нужно кеш ставить.


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 25, 2016, 12:53
Спасибо большое. Сейчас попробую.


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 25, 2016, 14:36
Спасибо. На том минимальном работает без проблем, а вот в самом проекте все равно висит, хотя это уже где-то еще проблемы вылезли, т.к. первая загрузка модели от 39 до 230 мс была, а потом обновление  в пределах 6 с идет...Может траблы где в работе с сокетом...


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 25, 2016, 16:43
Нашел еще одно узкое место: при обновлении данных с сервера я не очищал контейнер и постоянно обновлял все данные. Теперь при обновлении получаю не больше 100 записей в секунду (при загрузке получаю все записи - 1928). Тормозит и проблему пока не могу найти, хотя на много лучше стало. При обновлении затрачивается не более 70 мс, а при полной загрузке в районе 230 мс. Где может еще быть слабое место?


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 25, 2016, 16:50
На минимально компилируемом проекте (тот что выкладывал) сделал тоже, что и в реальных условиях, т.е. выставил кол-во объектов 1928 и время обновления раз в секунду и получил те же тормоза...Что можно еще сделать, чтобы получить плавный скрол в таблице?


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Bepec от Март 25, 2016, 17:44
Мб я уже устарел морально, но зачем вы дёргаете setData и insertRows на каждую запись?
Вот это вообще мне непонятно
Код:
  
    setData(id, tindex, status.data.speed, Qt::DisplayRole);

    tindex = index(row, 2);
    setData(id, tindex, status.state_move, Qt::DecorationRole);

    tindex = index(row, 3);
    setData(id, tindex, status.state_battery, Qt::DecorationRole);

    tindex = index(row, 4);
    setData(id, tindex, status.state_satellite, Qt::DecorationRole);

    tindex = index(row, 5);
    setData(id, tindex, status.state_communication, Qt::DecorationRole);


Интересная штука - вы создаёте сначала 2к записей и запихиваете в map, а потом запихиваете уже в модель... Что мешает пихать сразу при создании?

PS или я реально не понимаю замысла всей этой модели ???

update: Oo а это зачем?
Код:
resizeColumnsToContents();
    resizeRowsToContents();


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 25, 2016, 17:57
Вы имеете ввиду сразу вставлять в модель, без map?


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Bepec от Март 25, 2016, 18:06
Заменяем
Код:
    QModelCars::statuses_t statuses;

    for(int i = 0; i < 2000; i++)
    {
        QModelCars::status_t status;

        status.data.speed = 10;
        status.state_battery = true;
        status.state_communication = true;
        status.state_move = true;
        status.state_satellite = true;

        statuses[i + 1000] = status;
    }

    for(int key: statuses.keys())
    {
        m_model->addCar(key, statuses[key]);
    }

    resizeColumnsToContents();
    resizeRowsToContents();
на
Код:
for(int i = 0; i < 2000; i++)
{
QModelCars::status_t status;

status.data.speed = 10;
status.state_battery = true;
status.state_communication = true;
status.state_move = true;
status.state_satellite = true;

//statuses[i + 1000] = status;
m_model->addCar(i, status);
}
И получаем обработку в 2-3 мс при частоте обновление 1с, 2к записей. Никаких лагов. Правда размер колонок вам придётся чуть подправить ручками, но там ничего сложного, от вашей задачи зависит.

PS resizeColumnsToContents(); и resizeRowsToContents(); - зло. Они проходят по всем записям таблицы, по всем ячейкам, вычисляют максимальное значение длины/высоты и после этого всего меняют размеры у них всех... Это ЗЛО :D *дьявольский смех*

PPS можно ещё и убрать создание объекта за цикл, сэкономим пару десятков наносекунд :D


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 25, 2016, 18:14
Цитировать
Интересная штука - вы создаёте сначала 2к записей и запихиваете в map, а потом запихиваете уже в модель... Что мешает пихать сразу при создании?
Вот после этого вопроса я реально прозрел ;D. Наверное заработался, пора в отпуск:)...Спасибо большое - реально удалял гланды через ж...:)


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 25, 2016, 18:16
Вопрос не по теме:
не могу поменять пароль, а старый не помню и поэтому не могу следить за темой с мобильника. Письмо с сылкой на почту не доходит!

Сори за вопрос не по теме...


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Bepec от Март 25, 2016, 18:18
Там где то в разделе работа форума есть темка для связи. Напиши туда, мб поменяют или вышлют. Тут какая то засада с письмами :D


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 25, 2016, 18:22
Спасибо. На выходных переделаю загрузку данных и отпишусь.


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 27, 2016, 14:41
Спасибо. Переделал загрузку и все теперь работает. Остается вопрос - как подогнать размеры ячеек? Пробовал через делегат, но чтобы работал sizeHint надо опять же вызывать
Код:
resizeColumnsToContents()
и
Код:
resizeRowsToContents()
.


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Bepec от Март 27, 2016, 15:22
Зависит от задачи как бы... Вы вот приведите условия для размеров ячеек и мы вам ответим :D

PS по идее у вас все ячейки статичные должны быть. Никаких "разных" размеров быть не должно.


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 27, 2016, 15:45
у меня в двух первых колонках текст и размер соответственно должен меняться под длину текста, а в остальных иконки 16х16.


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Igors от Март 27, 2016, 16:53
у меня в двух первых колонках текст и размер соответственно должен меняться под длину текста, а в остальных иконки 16х16.
Тут надо как бы "наоборот": для иконок ставите setSectionResizeMode(QHeaderView::Fixed), для остальных QHeaderView::Stretch. И лучше перед этим сделать setStretchLastSection(false)


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 27, 2016, 17:01
Спасибо большое, попробую.


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 28, 2016, 08:51
Попробовал, но размеры остались прежними...


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 28, 2016, 09:05
попробовал QHeaderView::resizeToContents и программа начала тупо висеть...


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Bepec от Март 28, 2016, 11:13
Вы б поменьше Igors слушали :D Он силён в графике,не спорю, но тут не красные штаны :D

У вас простая ситуация - 2к записей обновляющихся. В любом из предложенных Igors вариантов, каждое обновление вызывает реакцию проверки длины. Вам же нужно убрать эту зависимость.

Самый простой способ - задать фиксированные размеры столбцов. 1 колонка - 8 цифр(99999999), 2 колонка - максимум 10 знаков(9999км/час), остальные по размеру иконки, 16*16 допустим. И проблема исчезнет.


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 28, 2016, 11:23
Вторая колонка, там где скорость, то можно установить фиксированный размер, а вот первая может быть 5 цифр (по умолчанию), а может быть и строка, а забить статически количество символов не очень хорошо :). А через делегаты можно решить эту проблему? Если через sizeHint, то опять же приходится вызывать resizeColumnsToContents.


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Igors от Март 28, 2016, 11:23
Вы б поменьше Igors слушали :D Он силён в графике,не спорю, но тут не красные штаны :D
Цитировать
Ну ничего, мы себя в табличках покажем-с
:)

Попробовал, но размеры остались прежними...
Меланхолия и смирение здесь неуместны :) Выкладывайте тестовый проект - быстрее дело будет


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 28, 2016, 11:32
сейчас подготовлю и выложу.


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 28, 2016, 11:39
Это тот же, что и выкладывал перед этим.


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Bepec от Март 28, 2016, 14:15
Тогда самое простое - написать свой делегат. Потому что "подбирать общий размер строки" для всех 2к + строк - это бред :)

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

Ммм... а насчёт подбирать размер строки - может и сработать. Если хранить наибольший размер в модельке, при изменении данных проверять на увеличение и заменять. Вполне может сработать :P


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Igors от Март 28, 2016, 14:51
Не понял где проблема. Убрал resizeColumns(rows)ToContents и добавил setSectionResize в конструктор таблицы (аттач). Что не устраивает?


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Bepec от Март 28, 2016, 14:53
Хех невнимательность многих сгубила :D


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 28, 2016, 15:19
Сейчас буду разбираться. В минимальном проекте работает, а вот в основном тормоза...


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 28, 2016, 15:31
Не могу понять где траблы, но на основном проекте висит и все...хз где искать...


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 28, 2016, 16:05
Убрать тормоза так и не получилось - буду разбираться...А как выделять строки через делегат? Подсунул свой делегат, чтобы изображения центрировало, а выделение не работает.


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Bepec от Март 28, 2016, 16:39
Ну как вариант отрисовывать самому :D Вроде все данные для этого есть, тень там наложить али ещё что :)


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 28, 2016, 16:56
это по сигналу clicked?


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 29, 2016, 16:35
Подскажите, а как перехватить событие scroll от QTableView, вернее определить что полоса прокрутки дошла до минимума или максимума? Я переопределил eventFilter и перехватываю событие QEvent::Scroll, но не смог найти как определить что уже достигли одного из пределов.
Спасибо.


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 29, 2016, 17:04
Спасибо, я думал через eventFilter, а здесь через сигнал. Значит так и сделаем.


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: VPS от Март 29, 2016, 17:06
По нечаянности ответ удалил. :)
Повторю снова:
Подскажите, а как перехватить событие scroll от QTableView, вернее определить что полоса прокрутки дошла до минимума или максимума? Я переопределил eventFilter и перехватываю событие QEvent::Scroll, но не смог найти как определить что уже достигли одного из пределов.
Спасибо.
Цитата: vps
Есть такой сигнал:
Код
C++ (Qt)
void QAbstractSlider::valueChanged(int value)


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 29, 2016, 17:25
Сигнал наверное не подойдет...У меня следующая ситуация: есть карта (QWebView) установленная как centalwidget и сверху панель с QTableView. При прокрутке колесиком мышки, когда полоса прокрутки доходит либо до верха, либо до низа начинает зумиться карта, т.к. она является родителем панели и мне надо запретить зум. Как это сделать? Я думал через eventFilter...


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: VPS от Март 29, 2016, 20:03
Сигнал наверное не подойдет...У меня следующая ситуация: есть карта (QWebView) установленная как centalwidget и сверху панель с QTableView. При прокрутке колесиком мышки, когда полоса прокрутки доходит либо до верха, либо до низа начинает зумиться карта, т.к. она является родителем панели и мне надо запретить зум. Как это сделать? Я думал через eventFilter...
Можно на "QTableView" поставить фильтр на событие "QEvent::Wheel", в котором возвращать "true" (чтобы обработка не передавалась далее).


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 29, 2016, 21:03
Спасибо большое. Попробую.


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Kurles от Март 30, 2016, 09:57
А как выделять строки через делегат? Подсунул свой делегат, чтобы изображения центрировало, а выделение не работает.
если достаточно дефолтного выделения, достаточно в начале void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; поместить следующий код:
Код
C++ (Qt)
   QStyleOptionViewItem opt = option;
   initStyleOption(&opt, index);
 
   const QWidget *widget = option.widget;
   QStyle *style = widget ? widget->style() : QApplication::style();
   style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, widget);
 
Если хочется своего выделения, обрати внимание на переменную QStyle::State QStyleOption::state (option.state)


Название: Re: Создание модели на основе QAbstractTableView
Отправлено: Larry от Март 30, 2016, 11:17
Да, спасибо, я уже это реализовал :)