Ответ 1
Модельный подход в Qt довольно универсален. Все модели наследуются от QAbstractItemModel. С помощью этого класса вы можете создавать довольно сложные макеты данных (списки, деревья, таблицы и т.д.), Но усилия для реализации тоже довольно высоки.
QStandardItemModel
к использованию классом будет QStandardItemModel
. Вы можете легко создать модель таблицы и добавить элементы, которые являются экземплярами QStandardItem
. Вы можете использовать следующий код для начала работы:
#include <QtGui>
QStandardItemModel* createModel(QObject* parent)
{
const int numRows = 10;
const int numColumns = 10;
QStandardItemModel* model = new QStandardItemModel(numRows, numColumns);
for (int row = 0; row < numRows; ++row)
{
for (int column = 0; column < numColumns; ++column)
{
QString text = QString('A' + row) + QString::number(column + 1);
QStandardItem* item = new QStandardItem(text);
model->setItem(row, column, item);
}
}
return model;
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QMainWindow window;
QTableView* view = new QTableView;
view->setModel(createModel(view));
window.setCentralWidget(view);
window.show();
return app.exec();
}
Понимаете, он очень прост в использовании. Однако недостатком является то, что вам необходимо предоставить данные через QStandardItem
, которые могут быть пустой тратой памяти. Например, предположим, что у вас есть несколько 100 МБ данных, которые вы хотите отобразить в представлении. Поскольку у вас уже есть данные, хранящиеся где-то, было бы предпочтительнее просто адаптировать их таким образом, чтобы их можно было использовать в представлении вместо создания QStandardItem
для каждой ячейки.
Именно здесь вступает игра QAbstractTableModel
. В следующем примере создается матрица с 250 000 записей. Вместо создания одного QStandardItem
для каждого элемента матрицы мы подклассом QAbstractTableModel
и реализуем три чистых виртуальных метода numRows()
, numColumns()
и data()
, которые возвращают количество строк, столбцов и отображаемых данных.
#include <QtGui>
class MatrixModel : public QAbstractTableModel
{
public:
MatrixModel(int numRows, int numColumns, double* data)
: m_numRows(numRows),
m_numColumns(numColumns),
m_data(data)
{
}
int rowCount(const QModelIndex& parent = QModelIndex()) const
{
return m_numRows;
}
int columnCount(const QModelIndex& parent = QModelIndex()) const
{
return m_numColumns;
}
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const
{
if (!index.isValid() || role != Qt::DisplayRole)
return QVariant();
// Return the data to which index points.
return m_data[index.row() * m_numColumns + index.column()];
}
private:
int m_numRows;
int m_numColumns;
double* m_data;
};
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// Create a matrix.
const int numRows = 500;
const int numColumns = 500;
double matrix[numRows][numColumns];
for (int i = 0; i < numRows; ++i)
for (int j = 0; j < numColumns; ++j)
matrix[i][j] = i + j;
// Create a model which adapts the data (the matrix) to the view.
MatrixModel model(numRows, numColumns, (double*)matrix);
QMainWindow window;
QTableView* view = new QTableView;
view->setModel(&model);
window.setCentralWidget(view);
window.show();
return app.exec();
}
Как вы можете видеть, модель не дублирует никаких данных, а просто служит адаптером. Если вам нужна еще большая гибкость, вы можете перейти в QAbstractItemModel
а event реализовать создание индексов модели, которые Qt использует для указания данных модели для чтения или записи.