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(通过重写 QSqlQueryModel
的 setData()
方法)
这种情况下最简单的选择是创建一个继承自 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
我有一个 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(通过重写 QSqlQueryModel
的 setData()
方法)
这种情况下最简单的选择是创建一个继承自 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