QTableview:根据其他列中的值显示特定列中的数据

QTableview: display data in specific column based on value in other column

我有一个 sqlite table 包含(除其他外)一个“position”和一个“state”字段。

我想在 QTableView 中显示此 table,位置为 header 列,状态在右列中,如下所示:

id | 1 | 2 | 3
1  | A |   |  
2  |   |   | E

代表以下数据库条目:

id | position | state
1  | 1        | A
2  | 3        | E

做这样的事情最好的方法是什么?

编辑:不确定这是否改变了什么,但我也需要 QTableView 编辑 table(通过重写 QSqlQueryModelsetData() 方法)

这种情况下最简单的选择是创建一个继承自 QSqlTableModel 的 class 并修改必要的函数,如下所示:

sqltablemodel.h

#ifndef SQLTABLEMODEL_H
#define SQLTABLEMODEL_H

#include <QSqlTableModel>

class SqlTableModel : public QSqlTableModel
{
    const QString stateName = "state";
    const QString positionName = "position";

public:
    int columnCount(const QModelIndex &parent = QModelIndex()) const;
    void setTable(const QString &tableName);
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
    QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
    Qt::ItemFlags flags(const QModelIndex &index) const;

   bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
private:
    int max_position;

    int index_position;
    int index_state;

    void reset();
};

#endif // SQLTABLEMODEL_H

sqltablemodel.cpp

#include "sqltablemodel.h"

#include <QBrush>
#include <QSqlQuery>
#include <QSqlTableModel>
#include <QSqlRecord>
#include <QTimer>


int SqlTableModel::columnCount(const QModelIndex &parent) const
{
    return QSqlTableModel::columnCount(parent)+ max_position;;
}

void SqlTableModel::setTable(const QString &tableName)
{

    QSqlTableModel::setTable(tableName);

    index_position = fieldIndex(positionName);
    index_state = fieldIndex(stateName);

    reset();
}

QVariant SqlTableModel::data(const QModelIndex &index, int role) const
{
    if(role == Qt::ForegroundRole){
        return QBrush(Qt::black);
    }
    const int number_of_columns = QSqlTableModel::columnCount();
    if(index.column()>= number_of_columns){
        if(role==Qt::DisplayRole){
            int position = QSqlTableModel::data(this->index(index.row(), index_position), Qt::DisplayRole).toInt();
            if(index.column() == number_of_columns + position - 1){
                return QSqlTableModel::data(this->index(index.row(), index_state), Qt::DisplayRole).toString();
            }
        }
    }
    return QSqlTableModel::data(index, role);
}

QVariant SqlTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if(orientation == Qt::Horizontal && role == Qt::DisplayRole && section >= QSqlTableModel::columnCount())
        return section -  QSqlTableModel::columnCount() + 1;
    return QSqlTableModel::headerData(section, orientation, role);
}

Qt::ItemFlags SqlTableModel::flags(const QModelIndex &index) const
{
    if(index.column() >= QSqlTableModel::columnCount()){
        return Qt::ItemIsSelectable| Qt::ItemIsEditable| Qt::ItemIsEnabled;
    }
    return QSqlTableModel::flags(index);
}

bool SqlTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if(role==Qt::EditRole){
        const int number_of_columns =  QSqlTableModel::columnCount();
        if(index.column() >= number_of_columns){
            bool result1 = QSqlTableModel::setData(this->index(index.row(), index_position), index.column()-number_of_columns +1, role);
            bool result2 = QSqlTableModel::setData(this->index(index.row(), index_state), value, role);

            return result1 && result2;
        }
        if(index.column() == index_position){
            QTimer::singleShot(0, this, &SqlTableModel::reset);
        }
    }

    return QSqlTableModel::setData(index, value, role);
}

void SqlTableModel::reset()
{
    QSqlQuery q;
    q.exec(QString("SELECT MAX(%1) FROM %2").arg(positionName).arg(tableName()));
    int val;
    while (q.next()) {
        val = q.value(0).toInt();
    }

    if(val != max_position){
        beginResetModel();
        max_position = val;
        endResetModel();
    }
}

输入:

id |position |state
1  |1        |A
2  |2        |S
3  |1        |C
4  |4        |B
5  |3        |V

输出:

完整的例子可以在下面找到link