Чтение онлайн

ЖАНРЫ

QT 4: программирование GUI на С++

Саммерфилд Марк

Шрифт:

QStringList cities;

cities << "Arvika" << "Boden" << "Eskilstuna" << "Falun"

<< "Filipstad" << "Halmstad" << "Helsingborg" << "Karlstad"

<< "Kiruna" << "Kramfors" << "Motala" << "Sandviken"

<< "Skara" << "Stockholm" << "Sundsvall" << "Trelleborg";

CityModel CityModel;

cityModel.setCities(cities);

QTableView tableView;

tableView.setModel(&cityModel);

tableView.setAlternatingRowColors(true);

Мы

должны переопределить те же самые функции, которые мы переопределяли в предыдущем примере. Кроме того, для обеспечения возможности редактирования модели мы должны переопределить setData и flags. Ниже приводится определение класса:

01 class CityModel : public QAbstractTableModel

02 {

03 Q_OBJECT

04 public:

05 CityModel(QObject *parent = 0);

06 void setCities(const QStringList &cityNames);

07 int rowCount(const QModelIndex &parent) const;

08 int columnCount(const QModelIndex &parent) const;

09 QVariant data(const QModelIndex &index, int role) const;

10 bool setData(const QModelIndex &index, const QVariant &value,

11 int role);

12 QVariant headerData(int section, Qt::Orientation orientation,

13 int role) const;

14 Qt::ItemFlags flags(const QModelIndex &index) const;

15 private:

16 int offsetOf(int row, int column) const;

17 QStringList cities;

18 QVector<int> distanсes;

19 };

В этой модели мы используем две структуры данных: cities типа QStringList для хранения названий городов, и distances типа QVector<int> для хранения расстояний между городами каждой уникальной пары.

01 CityModel::CityModel(QObject *parent)

02 : QAbstractTableModel(parent)

03 {

04 }

Конструктор передает параметр parent базовому классу и больше ничего не делает.

01 int CityModel::rowCount(const QModelIndex &

02 /* родительский элемент */) const

03 {

04 return cities.count;

05 }

06 int CityModel::columnCount(const QModelIndex &

07 /* родительский элемент */) const

08 {

09 return cities.count;

10 }

Поскольку мы имеем квадратную матрицу городов, количество строк и столбцов равно количеству городов в нашем списке.

01 QVariant CityModel::data(const QModelIndex &index, int role) const

02 {

03 if (!index.isValid)

04 return QVariant;

05 if (role == Qt::TextAlignmentRole) {

06 return int(Qt::AlignRight | Qt::AlignVCenter);

07 } else if (role == Qt::DisplayRole) {

08 if (index.row == index.column)

09 return 0;

10 int offset = offsetOf(index.row, index.column);

11 return distances[offset];

12 }

13 return QVariant;

14 }

Функция data

аналогична той же функции в нашей модели CurrencyModel. Она возвращает 0, если строка и столбец имеют одинаковый номер, потому что в этом случае два города одинаковы; в противном случае она находит в векторе distances элемент для заданной строки и заданного столбца, возвращая расстояние для этой конкретной пары городов.

01 QVariant CityModel::headerData(int section,

02 Qt::Orientation /* ориентация */,

03 int role) const

04 {

05 if (role == Qt::DisplayRole)

06 return cities[section];

07 return QVariant;

08 }

Функция headerData имеет простой вид, потому что наша таблица является квадратной матрицей, в которой строки и столбцы имеют идентичные заголовки. Мы просто возвращаем название города, расположенное с заданным смещением в списке строк cities.

01 bool CityModel::setData(const QModelIndex &index,

02 const QVariant &value, int role)

03 {

04 if (index.isValid && index.row != index.column

05 && role == Qt::EditRole) {

06 int offset = offsetOf(index.row, index.column);

07 distances[offset] = value.toInt;

08 QModelIndex transposedIndex = createIndex(

09 index.column, index.row);

10 emit dataChanged(index, index);

11 emit dataChanged(transposedIndex, transposedIndex);

12 return true;

13 }

14 return false;

15 }

Функция setData вызывается при редактировании элемента пользователем. Если индекс модели действителен, два города различны и модифицируемый элемент данных имеет ролевой атрибут Qt::EditRole, эта функция сохраняет введенное пользователем значение в векторе distances.

Функция createIndex используется для формирования индекса модели. Она нужна для получения индекса модели элемента, который расположен по другую сторону от главной диагонали и который соответствует элементу с установленным значением, поскольку оба элемента должны показывать одинаковые данные. Функция createIndex принимает сначала строку и затем столбец; здесь мы передаем параметры в обратном порядке, чтобы получить индекс модели элемента, расположенного по другую строну диагонали напротив элемента, определенного индексом index.

Поделиться с друзьями: