使用 QTableView 在 Qt C++ 中读取和查看制表符分隔的 txt 文件

Read and view tab-delimited txt files in Qt C++ using QTableView

我需要一些一般性建议来指出解决此问题的正确方向:我有一个包含 table 数据的 .txt 文件,如下所示:

Time    Pin
11:00   EIO4
12:55   EIO6
16:40   EIO4
20:10   EIO3

etc......

我需要能够解析此 .txt 文件。然后我需要在 Qt 中显示这个 table(可能在 QTableView 中)。

我研究过使用 QTableView,看来我使用 QTableView::setModel(QAbstractItemModel* model)QAbstractItemModel* 传递给 QTableView,之后我的 QTableView 将显示 QAbstractItemModel 中的任何数据(对吧?)。

如果最后一段是合乎逻辑的,那么我的下一个问题是如何使用我的 .txt 文件构建 QAbstractItemModel?我在文档中没有看到执行此操作的任何功能? (注意:有人建议创建一个 QStandardItemModel)

(注意,此段不再相关)QModelIndex createIndex(int row, int column, void* ptr) 似乎与此有关,也许吧?也许这会创建一个可以使用 QAbstractItemModel::insertRow(QModelIndex) 传递给 QAbstractItemModelQModelIndex?但是我仍然不知道如何使这些 QModelIndex 对象与我的 .txt 数据有任何关系。

QStandardItemModel 文档说

When you want a list or tree, you typically create an empty QStandardItemModel and use appendRow() to add items to the model, and item() to access an item. If your model represents a table, you typically pass the dimensions of the table to the QStandardItemModel constructor and use setItem() to position items into the table. You can also use setRowCount() and setColumnCount() to alter the dimensions of the model. To insert items, use insertRow() or insertColumn(), and to remove items, use removeRow() or removeColumn().

这些 "add rows" 的函数将 QList<QStandardItem*> 作为参数,所以我需要创建 QList,每个 QList 都包含包含每个单元格数据的指针 QStandardItems?

所以我会用

void QStandardItemModel::insertRow(int row, const QList<QStandardItem *> & items)

http://doc.qt.io/qt-5/qstandarditemmodel.html#insertRow

连同通过重复调用“<<”生成的参数 QList<QStandardItem*> 传递 QStandardItem* 指向空 QList 的指针。

我将使用构造函数

制作QStandardItem
QStandardItem::QStandardItem(const QString & text)

我通过将 QFile 解析为 QString 来获得我的 QString text

一切都很好吗?

或者我应该跳过创建 QList,直接从生成 QStandardItem 到使用 void QStandardItemModel::setItem(int row, int column, QStandardItem * item)

将它们传递到 QStandardItemModel

编辑: 我最终跳过了使用以下过程创建 QLists 的过程: QFile 文件 -> QString 行 -> QStringList 文件 -> QStandardItem -> QStandardItemModel -> QTableView

感谢所有贡献者

你的做法是正确的。您可以使用 QStandardItemModel 作为数据。

QStandardItemModel *model = new QStandardItemModel(2,3,this);
model->setHorizontalHeaderItem(0, new QStandardItem(QString("Column1 Header")));
model->setHorizontalHeaderItem(1, new QStandardItem(QString("Column2 Header")));
model->setHorizontalHeaderItem(2, new QStandardItem(QString("Column3 Header")));

ui->tableView->setModel(model);

你可以添加的值:

QStandardItem *firstRow = new QStandardItem(QString("ColumnValue"));
model->setItem(0,0,firstRow);

对于最初的问题,即如何创建自定义模型:这相当容易,因为 table 模型有一个方便的基础 class,QAbstractTableModel 实现了大部分通用模型接口的毛茸茸的方法。

自定义 table 模型的第一步是确定单行的数据类型,例如

struct Data
{
    QTime time;
    QString pin;
};

自定义模型随后可以对该类型的列表或向量进行操作。

class MyModel : public QAbstractItemModel
{
private:
    QVector<Data> m_data;
};

然后可以通过返回 list/vector 的 size/count 来简单地实现 rowCount() 方法,columnCount() 是固定的(本例中为 2)并且 data() 可以简单地访问 n-th 条目并打开请求的列:

QVariant MyModel::data(const QModelIndex &index, int role) const
{
    const Data &rowData = m_data[index.row()];

    switch (index.row()) {
    case 0: {
        if (role == Qt::DisplayRole) return rowData.time.toString("hh:mm"); // or whatever format you'd like
        else if (role == Qt::EditRole) return rowData.time; // return as QTime
        break;
    }
    case 1: if (role == Qt::DisplayRole || role == Qt::EditRole) return rowData.pin;
        break;
    default: break;
    }
    return QVariant();
}

可选择实施 headerData() 以获取 "Time" 和 "PIN" 作为列 headers