Инструменты пользователя

Инструменты сайта


develop:qt:model-view

Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

Следующая версия
Предыдущая версия
develop:qt:model-view [2021/11/01 04:03]
admin создано
develop:qt:model-view [2021/11/18 05:32] (текущий)
admin
Строка 4: Строка 4:
 ===== Модель (данных) ===== ===== Модель (данных) =====
  
 +{{ :develop:qt:qt-model_0.png?direct&600 |}}
  
-==== ====+Содержатся такие свойства как **index()**, **ItemDataRole()**, **flags()**, **match()**\\ 
 +**DataRole**- содержит много разных вариантов ролей данных\\
  
 +**ListModel**- простой, одномерный список\\
 +**StandartItemModel**- гораздо более сложная структура, каждая запись является отдельным итемом, с возможностью его настройки со-но.\\
  
-==== ====+Для использования, абстрактные классы необходимо наследовать, для работы необходимо определить как минимум три функции: **rowCount()**, **ColumnCount()** и **data()**.\\ 
 +Для хранения данных, внутри собственного класса, похоже нужно создавать собственные структуры данных, контейнеры и т.д. и сосбна обрабатывать их.\\
  
  
 +==== QModelIndex ====
 +Используется в качестве индекса в моделях, используется представлениями, делегатами, моделям выбора и поиска элементов.\\
 +Новые объекты создаются с помощью функции **QAbstractItemModel::createIndex()**, недействительный может быть построен с помощью конструктора **QModelIndex()**, недействительные часто используются в качестве родительских индексов, верхнего уровня.\\
 +
 +Индексы относятся к элементам и содержат всю информацию, необходимую для определения их местоположения.\\
 +**QAbstractItemModel::index()**- возвращает индекс на существующий элемент.\\
 +| bool **isValid()** | true если индекс принадлежит модели и имеет неотрицательные номера столбцов/строк |
 +| QModelIndex **sibling()** | возвращает "родственника" в указанной позиции оО |
 +| QVariant **data()** | возвращает данные для указанной роли |
  
  
 ===== Представление (данных) ===== ===== Представление (данных) =====
 +
 +{{ :develop:qt:qt-view_0.png?direct&600 |}}
 +
 +В представлении содержатся функции рисования/отображения, выбор, выделение записей.\\
 +
 +
 +===== Примеры =====
 +
 +==== Таблица ====
 +
 +<details>
 +<summary> :!: Простая таблица, минимум функций+ вставка/удаление строк/столбцов </summary>
 +:?: В ф-ции **beginInsertColumn**/**beginInsertRow**, нужно передавать корректные индексы, если передавать нули, то происходит вставка только одной записи, если не корректные цифры то все вообще по п*зде идет.\\
 +:?: Вставлять элементы можно как сразу в объект хранения (вектор/лист) так и ф-ями **insertColumn**/**insertRow**.\\
 +
 +
 +<code cpp-qt>
 +class VectorTableModel;
 +
 +class MWin : public QMainWindow
 +{
 +    Q_OBJECT
 +
 +    VectorTableModel *VModelTab;
 +    QTableView *VViewTab;
 +    QLineEdit *editDataForWrite;
 +    QPushButton *butAddRecord, *butAddColumn, *butDelRecord, *butDelColumn;
 +
 +public:
 +    MWin(QWidget *parent = nullptr);
 +
 +public slots:
 +    void slotInsertNewRecord();
 +    void slotInsertNewColumn();
 +    void slotDeleteSelectedRecord();
 +    void slotDeleteSelectedColumn();
 +};
 +
 +
 +class VectorTableModel: public QAbstractTableModel
 +{
 +    Q_OBJECT
 +
 +    QVector<QVector<QString> *> *LisIsData;
 +    QVector<QString> *HeadersList;
 +
 +public:
 +    VectorTableModel(QObject *parent= nullptr);
 +    ~VectorTableModel();
 +    
 +    // Минимальные
 +    QVariant data(const QModelIndex &index, int role= Qt::DisplayRole) const;
 +    int rowCount(const QModelIndex &parent= QModelIndex()) const;
 +    int columnCount(const QModelIndex &parent= QModelIndex()) const;
 +    
 +    // Переопределенные
 +    QVariant headerData(int section, Qt::Orientation orientation, int role) const;
 +    bool setData(const QModelIndex &index, const QVariant &value, int role);
 +    
 +    // Собственные
 +    void addRow(const QVector<QString> &vValues);
 +    void addColumn(qint32 vCount);
 +    void delRow(const qint32 &vNumberRow);
 +    void delColumn(const qint32 &vNumberCol);
 +
 +};
 +</code>
 +
 +<code cpp-qt>
 +#include "mwin.h"
 +
 +MWin::MWin(QWidget *parent): QMainWindow(parent)
 +{
 +    VModelTab= new VectorTableModel(this);
 +    VViewTab= new QTableView(this);
 +    VViewTab->setModel(VModelTab);
 +    VViewTab->setSelectionBehavior(QAbstractItemView::SelectionBehavior::SelectRows);
 +
 +    editDataForWrite= new QLineEdit(this);
 +    butAddRecord= new QPushButton("Новая запись", this);
 +    butAddColumn= new QPushButton("Новый столбец", this);
 +
 +    QHBoxLayout *layCtrls= new QHBoxLayout();
 +    layCtrls->addWidget(editDataForWrite, 1);
 +    layCtrls->addWidget(butAddRecord, 0);
 +    layCtrls->addWidget(butAddColumn, 0);
 +
 +    butDelRecord= new QPushButton("Удалить строку", this);
 +    butDelColumn= new QPushButton("Удалить столбец", this);
 +    QHBoxLayout *laySecondCtrls= new QHBoxLayout();
 +    laySecondCtrls->addWidget(butDelRecord);
 +    laySecondCtrls->addWidget(butDelColumn);
 +
 +    QVBoxLayout *layMain= new QVBoxLayout();
 +    layMain->addWidget(VViewTab, 2);
 +    layMain->addLayout(layCtrls);
 +    layMain->addLayout(laySecondCtrls);
 +
 +    QWidget *myWindow= new QWidget();
 +    myWindow->setLayout(layMain);
 +    setCentralWidget(myWindow);
 +
 +    connect(butAddRecord, &QPushButton::clicked, this, &MWin::slotInsertNewRecord);
 +    connect(butAddColumn, &QPushButton::clicked, this, &MWin::slotInsertNewColumn);
 +    connect(butDelRecord, &QPushButton::clicked, this, &MWin::slotDeleteSelectedRecord);
 +    connect(butDelColumn, &QPushButton::clicked, this, &MWin::slotDeleteSelectedColumn);
 +}
 +
 +
 +void MWin::slotInsertNewRecord()
 +{
 +    if(editDataForWrite->text().isEmpty())
 +    {
 +        QMessageBox::information(this, "Text", "Please input text");
 +        return;
 +    }
 +
 +    VModelTab->addDataRow(editDataForWrite->text().split(";", Qt::SkipEmptyParts));
 +    editDataForWrite->clear();
 +    editDataForWrite->setFocus();
 +}
 +
 +
 +void MWin::slotInsertNewColumn()
 +{
 +    if(editDataForWrite->text().isEmpty())
 +    {
 +        QMessageBox::information(this, "Text", "Please input count");
 +        return;
 +    }
 +    VModelTab->addColumn(editDataForWrite->text().toInt());
 +    editDataForWrite->clear();
 +    editDataForWrite->setFocus();
 +}
 +
 +
 +void MWin::slotDeleteSelectedRecord()
 +{
 +    VModelTab->delRow(VViewTab->currentIndex().row());
 +}
 +
 +
 +void MWin::slotDeleteSelectedColumn()
 +{
 +    VModelTab->delColumn(VViewTab->currentIndex().column());
 +}
 +
 +
 +//*********************************************************************|
 +//*********************************************************************|
 +
 +VectorTableModel::VectorTableModel(QObject *parent): QAbstractTableModel(parent)
 +{
 +    LisIsData= new QVector<QVector<QString>* >;
 +    HeadersList= new QVector<QString>;
 +}
 +
 +
 +VectorTableModel::~VectorTableModel()
 +{
 +    while(!LisIsData->isEmpty())
 +        delete LisIsData->takeFirst();
 +
 +    delete LisIsData;
 +    delete HeadersList;
 +}
 +
 +
 +QVariant VectorTableModel::data(const QModelIndex &index, int role) const
 +{
 +    if(role== Qt::DisplayRole)
 +        return LisIsData->at(index.row())->at(index.column());
 +    return QVariant();
 +}
 +
 +
 +int VectorTableModel::rowCount(const QModelIndex &parent) const
 +{
 +    Q_UNUSED(parent);
 +    return LisIsData->count();
 +}
 +
 +
 +int VectorTableModel::columnCount(const QModelIndex &parent) const
 +{
 +    Q_UNUSED(parent);
 +    return LisIsData->isEmpty() ? 0:LisIsData->at(0)->count();
 +}
 +
 +
 +QVariant VectorTableModel::headerData(int section, Qt::Orientation orientation, int role) const
 +{
 +    if(role!= Qt::DisplayRole)
 +        return QVariant();
 +
 +    if(orientation== Qt::Horizontal)
 +        return HeadersList->count() > section ? HeadersList->at(section):"";
 +    else
 +        return QString::number(section +1);
 +}
 +
 +
 +bool VectorTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
 +{
 +    if(index.isValid() && role== Qt::EditRole)
 +    {
 +        LisIsData->at(index.row())->replace(index.column(), value.toString());
 +        emit dataChanged(index, index);
 +        return true;
 +    }
 +
 +    return false;
 +}
 +
 +
 +
 +void VectorTableModel::addRow(const QVector<QString> &vValues)
 +{
 +    beginInsertRows(QModelIndex(), rowCount(), rowCount());
 +    QVector<QString> *vNewRow= new QVector<QString>(vValues);
 +
 +    // Подгоняем кол-во столбцов, к большему, либо в гриде (векторе) либо в новой строке
 +    if(columnCount() > vNewRow->count())
 +        vNewRow->resize(this->columnCount());
 +
 +    else if(columnCount() < vNewRow->count())
 +    {
 +        beginInsertColumns(QModelIndex(), columnCount(), columnCount()+ (vNewRow->count()- columnCount()) -1);
 +
 +        for(qint32 i= 0; i < LisIsData->count(); i++)
 +            LisIsData->at(i)->resize(vNewRow->count());
 +
 +        endInsertColumns();
 +    }
 +
 +    LisIsData->append(vNewRow);
 +    endInsertRows();
 +}
 +
 +
 +void VectorTableModel::addColumn(qint32 vCount)
 +{
 +    beginInsertColumns(QModelIndex(), columnCount(), columnCount()+ vCount -1);
 +    while(vCount--)
 +        this->insertColumn(columnCount());
 +    endInsertColumns();
 +}
 +
 +
 +void VectorTableModel::delRow(const qint32 &vNumberRow)
 +{
 +    beginInsertRows(QModelIndex(), vNumberRow, vNumberRow);
 +    if(LisIsData->count() > vNumberRow)
 +        LisIsData->remove(vNumberRow);
 +    endInsertRows();
 +}
 +
 +
 +void VectorTableModel::delColumn(const qint32 &vNumberCol)
 +{
 +    beginInsertColumns(QModelIndex(), vNumberCol, vNumberCol);
 +    if(HeadersList->count() > vNumberCol)
 +        HeadersList->remove(vNumberCol);
 +
 +    for(qint32 i= 0; i < LisIsData->count(); i++)
 +        LisIsData->at(i)->remove(vNumberCol);
 +    endInsertColumns();
 +}
 +</code>
 +</details>
 +
 +
  
  
-==== ==== 
  
-==== ==== 
  
  
-===== ===== 
  
develop/qt/model-view.1635739428.txt.gz · Последнее изменение: 2021/11/01 04:03 — admin