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

标签 c++ qt sqlite qt5 qtableview

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

我想在 QTableView 中显示此表,其位置作为标题列,状态在右列中,如下所示:

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

代表以下数据库条目:

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

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

编辑:不确定这是否会改变任何内容,但我也需要 QTableView 也可编辑(通过覆盖 QSqlQueryModelsetData() 方法) )

最佳答案

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

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

输出:

enter image description here

完整的示例可以在下面的link中找到。

关于c++ - QTableview:根据其他列中的值显示特定列中的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46169378/

相关文章:

c++ - 在为 "NaN"编写模板算法时,我们可以将什么作为 "most frequent value"返回?

c++ - 从模板基类派生

c++ - 调用QML处理程序,但使用 “undefined” c++信号参数

c++ - 在 Windows 中修改文件夹时通知我的应用程序?

java - 如何在java数组/列表中保存int和string列?

c++ - 使用成员作为参数调用构造函数解析为变量定义

c++ - 如何像 C++ const/constexpr 一样定义 CUDA 设备常量?

c++ - 从 C++ 获取 QML Editbox 的值

SQLite:从命令行插入二进制数据

php - PDO Sqlite 一般错误 : 25 bind or column index out of range