Чтение и просмотр текстовых файлов с разделителями табуляции в Qt C++ с использованием QTableView

Мне нужен общий совет, чтобы указать мне правильное направление решения этой проблемы: у меня есть файл .txt с табличными данными, например:

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

etc......

Мне нужно иметь возможность анализировать этот файл .txt. Затем мне нужно отобразить эту таблицу в Qt (возможно, в QTableView).

Я изучил использование QTableView, и, похоже, я передаю QAbstractItemModel* в QTableView с помощью QTableView::setModel(QAbstractItemModel* model), после чего мой QTableView будет отображать любые данные в QAbstractItemModel (правильно?).

Если этот последний абзац был логичным, то мой следующий вопрос: как мне создать QAbstractItemModel, используя мой файл .txt? Я не вижу никаких функций в документации, которые делают это? (Примечание: кто-то предложил создать QStandardItemModel)

(Обратите внимание, этот абзац больше не актуален) QModelIndex createIndex(int row, int column, void* ptr) может иметь к этому какое-то отношение? Может быть, это создает QModelIndex, который можно передать QAbstractItemModel с помощью QAbstractItemModel::insertRow(QModelIndex)? Однако я до сих пор не знаю, как заставить эти объекты QModelIndex иметь какое-либо отношение к моим данным .txt.

QStandardItemModel документация говорит

Когда вам нужен список или дерево, вы обычно создаете пустой QStandardItemModel и используете appendRow() для добавления элементов в модель, а item() для доступа к элементу. Если ваша модель представляет собой таблицу, вы обычно передаете размеры таблицы конструктору QStandardItemModel и используете setItem() для размещения элементов в таблице. Вы также можете использовать setRowCount() и setColumnCount() для изменения размеров модели. Чтобы вставить элементы, используйте insertRow() или insertColumn(), а чтобы удалить элементы, используйте removeRow() или removeColumn().

Эти функции, которые «добавляют строки», принимают QList<QStandardItem*> в качестве аргументов, поэтому мне нужно создать 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)

где я получаю свой QString text, анализируя QFile в QStrings.

Все выглядит хорошо?

Или, может быть, мне следует пропустить создание QList и сразу перейти от создания QStandardItem к передаче их в QStandardItemModel с помощью void QStandardItemModel::setItem(int row, int column, QStandardItem * item)

Изменить: в итоге я пропустил создание QLists со следующим процессом: файл QFile -> строка QString -> фрагменты QStringList -> QStandardItem -> QStandardItemModel -> QTableView

Спасибо всем, кто внес свой вклад


person OrangeSherbet    schedule 20.04.2015    source источник
comment
Вы не можете создать абстрактную модель, она абстрактна. Вам нужно будет создать подкласс. Вы можете просмотреть документы для получения дополнительной информации об этом: doc.qt.io/ qt-5/qabstracttablemodel.html   -  person Retired Ninja    schedule 20.04.2015
comment
Я посмотрел, там написано, что мой подкласс QAbstractTableModel должен реализовывать QVariant QAbstractItemModel::data(const QModelIndex & index, int role = Qt::DisplayRole) const, но я не знаю, как создавать объекты QModelIndex, которые имеют какое-либо отношение к моему .txt файлу?! Я добавил абзац к своему вопросу.   -  person OrangeSherbet    schedule 20.04.2015


Ответы (2)


Ваш подход правильный. Вы можете использовать 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);
person gomons    schedule 20.04.2015
comment
Это не ответ, это в лучшем случае достойный комментарий. - person ; 20.04.2015

Что касается исходного вопроса, то есть как создать пользовательскую модель: это довольно просто, потому что для табличных моделей существует удобный базовый класс QAbstractTableModel, который реализует большинство сложных методов общего интерфейса модели.

Первым шагом для пользовательской модели таблицы является выбор типа данных для одной строки, например.

struct Data
{
    QTime time;
    QString pin;
};

Затем пользовательская модель может работать со списком или вектором этого типа.

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

Затем можно просто реализовать метод rowCount(), возвращая размер/количество списка/вектора, columnCount() является фиксированным (2 в этом примере), а data() может просто получить доступ к n-й записи и переключиться на запрошенный столбец:

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(), чтобы получить «Время» и «ПИН-код» в качестве заголовков столбцов.

person Kevin Krammer    schedule 18.09.2016