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

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


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() возвращает данные для указанной роли

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

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

Примеры

Таблица

:!: Простая таблица, минимум функций+ вставка/удаление строк/столбцов
class myTableModel;
 
class MWin : public QMainWindow
{
    Q_OBJECT
 
    myTableModel *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 myTableModel: public QAbstractTableModel
{
    Q_OBJECT
 
    QList<QList<QString> *> myDataInCell;
    // Независимый список столбцов плох тем что при удалении, 
        // содержимое таблицы ведь не удаляется
    QList<QString *> ListHeaders;
 
public:
    myTableModel(QObject *parent= nullptr);
 
    // Минимальные ф-ии
    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 addDataRow(const QList<QString> &vValues);
    void addColumn(const QString&);
    void delRow(qint32 NumberRow);
    void delColumn(qint32 NumberCol);
};
#include "mwin.h"
 
 
MWin::MWin(QWidget *parent): QMainWindow(parent)
{
    VModelTab= new myTableModel(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 text");
        return;
    }
    VModelTab->addColumn(editDataForWrite->text());
    editDataForWrite->clear();
    editDataForWrite->setFocus();
}
 
 
void MWin::slotDeleteSelectedRecord()
{
    VModelTab->delRow(VViewTab->currentIndex().row());
}
 
 
void MWin::slotDeleteSelectedColumn()
{
    VModelTab->delColumn(VViewTab->currentIndex().column());
}
 
 
//*********************************************************************|
//*********************************************************************|
 
myTableModel::myTableModel(QObject *parent): QAbstractTableModel(parent)
{
 
}
 
// QList->value()- проверяет границы; ->at()- быстрее но не проверяет границы
// []- создает копию списка, если он является общим во время обращения, полезно для редактирования
QVariant myTableModel::data(const QModelIndex &index, int role) const
{
    if(role== Qt::DisplayRole) // || (==Qt::EditRole)|| (==Qt::BackgroundRole)
        return myDataInCell.value(index.row())->value(index.column());
    return QVariant();
}
 
 
int myTableModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent); // Просто чтобы не было варнинга о неиспользуемой переменной
    return ListHeaders.count();
}
 
 
int myTableModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return myDataInCell.count();
}
 
 
void myTableModel::addDataRow(const QList<QString> &vValues)
{
    // Единственное только с цифрами тут: вообще это координаты новых строк, 
      // вставляем мы тут по одной, хз, с нолями работает, с некоторыми значениями не работает
    this->beginInsertRows(QModelIndex(), 0, 0);
    myDataInCell.append(new QList<QString>(vValues));
    this->endInsertRows();
}
 
 
QVariant myTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if(role != Qt::DisplayRole)
        return QVariant();
    if(orientation == Qt::Horizontal)
        return *ListHeaders.value(section);
    else
        return QString::number(section +1); // номера строк
}
 
 
void myTableModel::addColumn(const QString &vNameNewCol)
{
    this->beginInsertColumns(QModelIndex(), 0, 0);
    ListHeaders.append(new QString(vNameNewCol));
    this->endInsertColumns();
}
 
 
void myTableModel::delRow(qint32 NumberRow)
{
    this->beginRemoveRows(QModelIndex(), 0,0);
    delete myDataInCell.value(NumberRow); // Освобождение ячейки памяти
    myDataInCell.removeAt(NumberRow); // Удаление ссылки на нее из списка
    this->endRemoveRows();
}
 
 
void myTableModel::delColumn(qint32 NumberCol)
{
    this->beginRemoveColumns(QModelIndex(), 0,0);
    delete ListHeaders.value(NumberCol);
    ListHeaders.removeAt(NumberCol);
    this->endRemoveColumns();
}
 
 
// Еще не используется, нужна для редактирования записей
bool myTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if(index.isValid() && role== Qt::EditRole)
    {
        // ??? Проверка границ списка ???
        myDataInCell[index.row()]->replace(index.column(), value.toString());
        emit dataChanged(index, index);
        return true;
    }
 
    return false;
}
develop/qt/model-view.1635924308.txt.gz · Последнее изменение: 2021/11/03 07:25 — admin