Comprensión del modelo/vista Qt 01

Hay dos formas principales de procesar datos en Qt: 1) Operar directamente el elemento de datos que contiene los datos. Este método es simple y fácil de operar, pero tiene la desventaja de un método único, especialmente para big data o repetido en diferentes ubicaciones. Los datos que aparecen deben operarse en secuencia. Si el modo real cambia, los datos deberán recodificarse durante el proceso de modificación del programa, lo que consume mano de obra y recursos. 2) Utilice el modelo / modelo de vista para unir datos - modelo - vista y garantizar la visualización correcta de los datos y la diversidad de métodos de visualización a través de la interfaz acordada. Cuando es necesario reajustar la visualización, solo necesita modificar la vista para garantizar que la interfaz permanezca sin cambios, es decir, los datos se pueden mostrar en una nueva vista.

1/2 Dos formas de procesar datos:

Las vistas están vinculadas a datos:

Vista y aislamiento de datos:

Aquí, presento principalmente el segundo modelo: modo modelo/vista, tomando QAbstractTableModel/QTableView como ejemplo.

Si está en modo de solo lectura, el modelo solo necesita anular los tres métodos siguientes:

//a方法:返回模型行数。
int rowCount(const QModelIndex &parent) const; 

//b方法:返回模型列数。
int columnCount(const QModelIndex &parent) const; 

//c方法:返回index项的role角色的数据。其中index项中可以有多个角色,每个角色都可以有一个数据。
QVariant data(const QModelIndex &index, int role) const;

Si el usuario desea poder editar datos (modo de edición), el modelo también debe anular los dos métodos siguientes:

//d方法:设置模型中项的内容。
bool QAbstractItemModel::setData(const QModelIndex & index, 
                                 const QVariant & value, 
                                 int role= Qt::EditRole);

//e方法:返回项的编辑形式,默认情况下只有ItemIsSelectable和ItemIsEnabled,如果要可编辑,需要
//添加ItemIsEditable属性。
Qt::ItemFlags QAbstractTableModel::flags(const QModelIndex & index) const

Los métodos a/b/c son métodos virtuales puros y la clase heredada debe implementar este método mediante el propio codificador. El método d/e es una función virtual. El codificador hereda este método y puede llamar directamente al método de la clase base después de implementar contenido personalizado.

Aquí utilizamos el ejemplo de trackEditor en "Programación GUI en C++ con Qt4" para explicarlo.

class MyTableModel : public QAbstractTableModel
{
public:
    explicit MyTableModel(QList<Track>* tracks, QWidget *parent = 0);

    virtual int rowCount(const QModelIndex &parent) const;
    virtual int columnCount(const QModelIndex &parent) const;
    virtual QVariant data(const QModelIndex &index, int role) const;
    virtual QVariant headerData(int section,
                                Qt::Orientation orientation,
                                int role) const;
    virtual Qt::ItemFlags flags(const QModelIndex &index) const;
    virtual bool setData(const QModelIndex &index, const QVariant &value, int role);

private:
    QList<Track>* pTracks;
};

Entre ellos, "QList<Track>* tracks" se utiliza para guardar la recopilación de datos mostrada por el modelo, se asigna cuando se inicializa el modelo y los datos se muestran de acuerdo con el algoritmo del método de datos.

MyTableModel::MyTableModel(QList<Track>* tracks, QWidget *parent)
{
    Q_UNUSED(parent);

    pTracks = tracks;
}

El constructor asigna valores a las pistas.

int MyTableModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);

    return pTracks->count();
}

int MyTableModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);

    return 2;
}

Los dos métodos anteriores devuelven el número de filas/columnas del modelo. Debido a que la cantidad de datos en las pistas es incierta, su método de conteo se devuelve directamente para garantizar el último valor cada vez;

QVariant MyTableModel::data(const QModelIndex &index, int role) const
{
    if ( !index.isValid()) {
        return QVariant();
    }

    if (Qt::DisplayRole == role || Qt::EditRole == role) {
        if (0 == index.column()) {
            return pTracks->at(index.row()).getTitle();
        } else if (1 == index.column()) {
            return pTracks->at(index.row()).getDuration();
        }
    }

    return QVariant();
}

Dependiendo del tipo de datos y la columna, se devuelve información de datos diferente. Cuando el índice no se encuentra en las dos situaciones anteriores, se devuelve un objeto QVariant. EditRole garantiza que cuando el usuario edita datos, los datos aparecen en el modo seleccionado en lugar de desaparecer directamente.

bool MyTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if ( !index.isValid()) {
        return false;
    }

    if (Qt::EditRole == role) {
        (*pTracks)[index.row()].setTitle(value.toString());
        emit dataChanged(index, index);

        return true;
    } else {
        return QAbstractTableModel::setData(index, value, role);
    }
}

De acuerdo con el procesamiento del codificador y la función entrante, establezca el valor del elemento de índice y los datos correspondientes en las pistas y actualice la visualización de datos de índice. Cuando el codificador de datos entrantes no los procesa, llama directamente al método de clase base para procesarlos. No especifica qué columna editar porque las columnas editables se configuran más tarde a través del método flags, por lo que no es necesario especificarlo aquí. . Tenga en cuenta aquí que el método setData determina la función Qt::EditRole, y el método de datos es Qt::DisplayRole, pero lo que se guarda y lee son pistas. Esto es a lo que el codificador debe prestar atención. En diferentes procesos, el programa Los roles que ocupan son diferentes, pero todos operan la misma base de datos (pistas), esto es digno de mención.

Qt::ItemFlags MyTableModel::flags(const QModelIndex &index) const
{
    if (0 == index.column()) {
        return (QAbstractTableModel::flags(index) | Qt::ItemIsEditable);
    } else {
        return QAbstractTableModel::flags(index);
    }
}

El indicador de procesamiento de cada elemento en el modelo tiene como valor predeterminado (ItemIsEnabled | ItemIsSelectable), y el codificador puede configurar elementos con diferentes atributos según sea necesario. Aquí, configure la columna 0 para que sea editable y las columnas restantes para que no se puedan editar.

Los resultados de ejecución del programa muestran los mismos datos usando TableView y ListView respectivamente:

El código específico es el siguiente: Hay tres clases: maindialg, mytablemodel, tack y una clase de ejecución principal. El archivo de interfaz específico es la interfaz de usuario generada por el propio Qt.

pista.h

#ifndef TRACK_H
#define TRACK_H

#include <QString>

class Track
{
public:
    explicit Track(const QString& title = "", int duration = 0);

    QString getTitle() const;
    int getDuration() const;

    void setDuration(int duration);
    void setTitle(QString title);

private:
    QString mTitle;
    int mDuration;
};

#endif // TRACK_H

pista.cpp

#include "track.h"

Track::Track(const QString &title, int duration) :
    mTitle(title),
    mDuration(duration)
{

}

QString Track::getTitle() const
{
    return mTitle;
}

int Track::getDuration() const
{
    return mDuration;
}

void Track::setDuration(int duration)
{
    mDuration = duration;
}

void Track::setTitle(QString title)
{
    mTitle = title;
}

mytablemodel.h

#ifndef MYTABLEMODEL_H
#define MYTABLEMODEL_H

#include <QWidget>
#include <QAbstractTableModel>
#include "track.h"

class MyTableModel : public QAbstractTableModel
{
public:
    explicit MyTableModel(QList<Track>* tracks, QWidget *parent = 0);

    virtual int rowCount(const QModelIndex &parent) const;
    virtual int columnCount(const QModelIndex &parent) const;
    virtual QVariant data(const QModelIndex &index, int role) const;
    virtual QVariant headerData(int section,
                                Qt::Orientation orientation,
                                int role) const;
    virtual Qt::ItemFlags flags(const QModelIndex &index) const;
    virtual bool setData(const QModelIndex &index, const QVariant &value, int role);

private:
    QList<Track>* pTracks;
};

#endif // MYTABLEMODEL_H

mitablemodel.cpp

#include "mytablemodel.h"

MyTableModel::MyTableModel(QList<Track>* tracks, QWidget *parent)
{
    Q_UNUSED(parent);

    pTracks = tracks;
}

int MyTableModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);

    return pTracks->count();
}

int MyTableModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);

    return 2;
}

QVariant MyTableModel::data(const QModelIndex &index, int role) const
{
    if ( !index.isValid()) {
        return QVariant();
    }

    if (Qt::DisplayRole == role) {
        if (0 == index.column()) {
            return pTracks->at(index.row()).getTitle();
        } else if (1 == index.column()) {
            return pTracks->at(index.row()).getDuration();
        }
    }

    return QVariant();
}

QVariant MyTableModel::headerData(int section,
                                  Qt::Orientation orientation,
                                  int role) const
{
    /*if (Qt::Vertical == orientation) {
        return QVariant();
    }*/

    if (Qt::DisplayRole == role && Qt::Horizontal == orientation) {
        switch (section) {
        case 0:
            return "first";

        case 1:
            return "second";
        }
    }

    return QVariant();
}

Qt::ItemFlags MyTableModel::flags(const QModelIndex &index) const
{
    if (0 == index.column()) {
        return (QAbstractTableModel::flags(index) | Qt::ItemIsEditable);
    } else {
        return QAbstractTableModel::flags(index);
    }
}

bool MyTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if ( !index.isValid()) {
        return false;
    }

    if (Qt::EditRole == role) {
        (*pTracks)[index.row()].setTitle(value.toString());
        emit dataChanged(index, index);

        return true;
    } else {
        return QAbstractTableModel::setData(index, value, role);
    }
}

diálogo principal.h

#ifndef MAINDIALOG_H
#define MAINDIALOG_H

#include <QDialog>
#include <QTableView>
#include <QListView>
#include "mytablemodel.h"

namespace Ui {
class MainDialog;
}

class MainDialog : public QDialog
{
    Q_OBJECT

public:
    explicit MainDialog(QWidget *parent = 0);
    ~MainDialog();

    void setTableModel(MyTableModel* model);

    void setListModel(MyTableModel* model);

private:
    Ui::MainDialog *ui;

    QTableView* pTableView;
    QListView* pListView;
};

#endif // MAINDIALOG_H

diálogo principal.cpp

#include<QGridLayout>
#include "maindialog.h"
#include "ui_maindialog.h"

MainDialog::MainDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::MainDialog),
    pTableView(new QTableView(this)),
    pListView(new QListView(this))
{
    ui->setupUi(this);

    QVBoxLayout* layout(new QVBoxLayout(this));
    layout->addWidget(pTableView);
    layout->addWidget(pListView);
    setLayout(layout);

    setAttribute(Qt::WA_DeleteOnClose);
}

MainDialog::~MainDialog()
{
    delete ui;
}

void MainDialog::setTableModel(MyTableModel *model)
{
    pTableView->setModel(model);
}

void MainDialog::setListModel(MyTableModel* model)
{
    pListView->setModel(model);
}

principal.cpp

#include <QApplication>
#include "maindialog.h"
#include "track.h"
#include "mytablemodel.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QList<Track> tracks;
        tracks << Track("The Flying Dutchman: Overture", 630)
               << Track("The Flying Dutchman: Wie aus der Fern laengst "
                        "vergangner Zeiten", 374)
               << Track("The Flying Dutchman: Steuermann, lass die Wacht",
                        152)
               << Track("Die Walkuere: Ride of the Valkyries", 286)
               << Track("Tannhaeuser: Freudig begruessen wir die edle "
                        "Halle", 384)
               << Track("Tannhaeuser: Wie Todesahnung - O du mein holder "
                        "Abendstern", 257)
               << Track("Lohengrin: Treulich gefuert ziehet dahnin", 294)
               << Track("Lohengrin: In fernem Land", 383)
               << Track("Die Meistersinger von Nuernberg: Overture", 543)
               << Track("Die Meistersinger von Nuernberg: Verachtet mir "
                        "die Meister nicht", 200)
               << Track("Die Meistersinger von Nuernberg: Ehrt eure "
                        "deutschen Meister", 112)
               << Track("Goetterdaemmerung: Funeral Music", 469)
               << Track("Tristan und Isolde: Mild und leise, wie er "
                        "laechelt", 375);

    MyTableModel model(&tracks);

    MainDialog* w(new MainDialog(0));
    w->setTableModel(&model);
    w->setListModel(&model);
    w->show();

    return a.exec();
}

Supongo que te gusta

Origin blog.csdn.net/weiweiqiao/article/details/133562285
Recomendado
Clasificación