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

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


develop:qt:model-view

Модель-представление

Модель (данных)

Содержатся такие свойства как index(), ItemDataRole(), flags(), match()
DataRole- содержит много разных вариантов ролей данных

ListModel- простой, одномерный список
StandartItemModel- гораздо более сложная структура, каждая запись является отдельным итемом, с возможностью его настройки со-но.

Для использования, абстрактные классы необходимо наследовать, для работы необходимо определить как минимум три функции: rowCount(), ColumnCount() и data().
Для хранения данных, внутри собственного класса, похоже нужно создавать собственные структуры данных, контейнеры и т.д. и сосбна обрабатывать их.

QModelIndex

Используется в качестве индекса в моделях, используется представлениями, делегатами, моделям выбора и поиска элементов.
Новые объекты создаются с помощью функции QAbstractItemModel::createIndex(), недействительный может быть построен с помощью конструктора QModelIndex(), недействительные часто используются в качестве родительских индексов, верхнего уровня.

Индексы относятся к элементам и содержат всю информацию, необходимую для определения их местоположения.
QAbstractItemModel::index()- возвращает индекс на существующий элемент.

bool isValid() true если индекс принадлежит модели и имеет неотрицательные номера столбцов/строк
QModelIndex sibling() возвращает «родственника» в указанной позиции оО
QVariant data() возвращает данные для указанной роли

Представление (данных)

В представлении содержатся функции рисования/отображения, выбор, выделение записей.

Примеры

Таблица

:!: Простая таблица, минимум функций+ вставка/удаление строк/столбцов

:?: В ф-ции beginInsertColumn/beginInsertRow, нужно передавать корректные индексы, если передавать нули, то происходит вставка только одной записи, если не корректные цифры то все вообще по п*зде идет.
:?: Вставлять элементы можно как сразу в объект хранения (вектор/лист) так и ф-ями insertColumn/insertRow.

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);
 
};
#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();
}
develop/qt/model-view.txt · Последнее изменение: 2021/11/18 05:32 — admin