Саммерфилд Марк - QT 4: программирование GUI на С++ стр 25.

Шрифт
Фон

Рис. 4.9. Помещение данных в таблицу после сортировки.

После выполнения функции qStableSort() мы помещаем данные обратно в таблицу, сбрасываем выделение области и вызываем функцию somethingChanged(). Класс SpreadsheetCompare в spreadsheet.h определен следующим образом:

01 class SpreadsheetCompare

02 {

03 public:

04 bool operator()(const QStringList &row1,

05 const QStringList &row2) const;

06 enum { KeyCount = 3 };

07 int keys[KeyCount];

08 bool ascending[KeyCount];

09 };

Класс SpreadsheetCompare является специальным классом, реализующим оператор (). Это позволяет нам применять этот класс в качестве функции. Такие классы называются объектами функций или функторами (functors).

Для лучшего понимания работы функторов мы сначала разберем простой пример:

01 class Square

02 {

03 public:

04 int operator()(int x) const { return x * x; }

05 }

Класс Square содержит одну функцию operator()(int), которая возвращает квадрат переданного ей значения параметра. Обозначая функцию в виде operator()(int), а не в виде, например, compute(int), мы получаем возможность применения объекта типа Square как функции:

Square square;

int у = square(5);

Теперь рассмотрим пример с применением объекта SpreadsheetCompare:

QStringList row1, row2;

QSpreadsheetCompare compare;

if (compare(row1, row2)) {

// строка row1 меньше, чем row2

}

Объект compare можно использовать так же, как если бы он был обычной функцией compare().

устарело.

Мы используем QVariant, поскольку некоторые ячейки имеют тип числа двойной точности double, а другие имеют тип строки QString.

При объявлении переменных cachedValue и cacheIsDirty используется ключевое слово mutable языка С++. Это позволяет нам модифицировать эти переменные в функциях с модификатором const. Мы могли бы поступить по-другому и заново выполнять расчет при каждом вызове функции text(), но эта неэффективность будет не оправдана.

Следует отметить, что в определении класса не используется макрос Q_OBJECT. Класс Cell является «чистым» классом С++, который не имеет сигналов и слотов. На самом деле из-за того, что QTableWidgetltem не является наследником QObject, мы не можем использовать в Cell как таковые сигналы и слоты. Классы элементов Qt не наследуют QObject, чтобы свести к минимуму затраты на их обработку. Если сигналы и слоты необходимы, они могут быть реализованы в виджете, содержащем элементы, или (в виде исключения) при помощи множественного наследования класса QObject.

Теперь мы перейдем к написанию cell.cpp:

01 #include <QtGui>

02 #include "cell.h"

03 Cell::Cell()

04 {

05 setDirty();

06 }

В конструкторе нам необходимо установить признак «dirty» («грязный») только для кэша. Передавать родительский объект нет необходимости; когда делается вставка ячейки в QTableWidget с помощью setItem(), QTableWidget автоматически станет ее владельцем.

Каждый элемент QTableWidgetltem может иметь некоторые данные до одного типа QVariant на каждую «роль» данных. Наиболее распространенными ролями являются Qt::EditRole и Qt::DisplayRole (роль правки и роль отображения). Роль правки используется для данных, которые должны редактироваться, а роль отображения для данных, которые должны отображаться на экране. Часто обе роли используются для одних и тех же данных, однако в Cell роль правки соответствует формуле ячейки, а роль отображения значению ячейки (результату вычисления формулы).

02 QTableWidgetltem *Cell::clone() const

03 {

04 return new Cell(*this);

05 }

Функция clone() вызывается в QTableWidget, когда необходимо создать новую ячейку, например когда пользователь начинает вводить данные в пустую ячейку, которая до сих пор не использовалась. Переданный функции QTableWidget::setItemPrototype() экземпляр является дубликатом. Поскольку для копирования Cell можно ограничиться функциейчленом, мы полагаемся на используемый по умолчанию конструктор копирования, автоматически создаваемый С++ при создании экземпляров новых ячеек Cell в функции clone().

06 void Cell::setFormula(const QString &formula)

07 {

08 setData(Qt::EditRole, formula);

09 }

Функция setFormula() задает формулу ячейки. Это просто удобная функция для вызова setData() с указанием роли правки. Она вызывается из функции Spreadsheet::setFormula().

10 QString Cell::formula() const

11 {

12 return data(Qt::EditRole).toString();

13 }

Функция formula() вызывается из Spreadsheet::formula(). Подобно setFormula() этой функцией удобно пользоваться на этот раз для получения данных EditRole заданного элемента.

14 void Cell::setData(int role, const QVariant &value)

15 {

16 QTableWidgetltem::setData(role, value);

17 if (role == Qt::EditRole)

18 setDirty();

19 }

Если мы имеем новую формулу, мы устанавливаем cacheIsDirty на значение true, чтобы обеспечить перерасчет ячейки при последующем вызове text().

В Cell нет определения функции text(), хотя мы и вызываем text() для экземпляров Cell в функции Spreadsheet::text(). QTableWidgetltem содержит удобную функцию text(), которая эквивалентна вызову data(Qt::DisplayRole).toString().

Ваша оценка очень важна

0
Шрифт
Фон

Помогите Вашим друзьям узнать о библиотеке