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

ЖАНРЫ

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

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

Шрифт:

42 class SpreadsheetCompare

43 {

44 public:

45 bool operator(const QStringList &row1, const QStringList &row2) const;

46 enum { KeyCount = 3 };

47 int keys[KeyCount];

48 bool ascending[KeyCount];

49 };

50 #endif

Заголовочный файл заканчивается определением класса SpreadsheetCompare. Мы объясним назначение этого класса при рассмотрении функции Spreadsheet::sort.

Теперь мы рассмотрим реализацию:

01 #include <QtGui>

02 #include "cell.h"

03 #include "spreadsheet.h"

04 Spreadsheet::Spreadsheet(QWidget *parent)

05 : QTableWidget(parent)

06 {

07 autoRecalc = true;

08 setItemPrototype(new Cell);

09 setSelectionMode(ContiguousSelection);

10 connect(this, SIGNAL(itemChanged(QTableWidgetItem *)),

11 this, SLOT(somethingChanged));

12 clear;

13 }

Обычно

при вводе пользователем некоторого текста в пустую ячейку QTableWidget будет автоматически создавать элемент QTableWidgetltem для хранения этого текста. Вместо этого мы хотим, чтобы создавались элементы Cell. Это достигается с помощью вызова в конструкторе функции setItemPrototype. Всякий раз, когда требуется новый элемент, QTableWidget дублирует элемент, переданный в качестве прототипа.

Кроме того, в конструкторе мы устанавливаем режим выделения области на значение QAbstractItemView::ContiguousSelection, чтобы могла быть выделена только одна прямоугольная область. Мы соединяем сигнал itemChanged виджета таблицы с закрытым слотом somethingChanged; это гарантирует вызов слота somethingChanged при редактировании ячейки пользователем. Наконец, мы вызываем clear для изменения размеров таблицы и задания заголовков столбцов.

14 void Spreadsheet::clear

15 {

16 setRowCount(0);

17 setColumnCount(0);

18 setRowCount(RowCount);

19 setColumnCount(ColumnCount);

20 for (int i = 0; i < ColumnCount; ++i) {

21 QTableWidgetltem *item = new QTableWidgetltem;

22 item->setText(QString(QChar('A' + i)));

23 setHorizontalHeaderItem(i, item);

24 }

25 setCurrentCell(0, 0);

26 }

Функция clear вызывается из конструктора Spreadsheet для инициализации электронной таблицы. Она также вызывается из MainWindow::newFile.

Мы могли бы использовать QTableWidget::clear для очистки всех элементов и любых выделений, но в этом случае заголовки имели бы текущий размер. Вместо этого мы уменьшаем размер электронной таблицы до 0 × 0. Это приводит к очистке всей электронной таблицы, включая заголовки. Затем мы опять устанавливаем ее размер на ColumnCount × RowCount (26 × 999) и заполняем строку горизонтального заголовка элементами QTableWidgetltem, содержащими обозначения столбцов. Нам не надо задавать метки строк, потому что по умолчанию строки обозначаются как «1», «2», … «26». В конце мы перемещаем курсор на ячейку A1.

Рис. 4.2.

Виджеты, составляющие QTableWidget.

QTableWidget содержит несколько дочерних виджетов. Сверху располагается горизонтальный заголовок QHeaderView, слева — вертикальный заголовок QHeaderView и две полосы прокрутки QScrollBar. В центральной области размещается специальный виджет, называемый областью отображения (viewport), в котором QTableWidget вычерчивает ячейки. Доступ к различным дочерним виджетам осуществляется с помощью функций, унаследованных от QTableView и QAbstractScrollArea (рис. 4.2). QAbstractScrollArea содержит перемещаемую область отображения и две полосы прокрутки, которые могут включаться и отключаться. Подкласс QScrollArea рассматривается в главе 6 .

Хранение данных в объектах типа «элемент»

В приложении Электронная таблица каждая непустая ячейка хранится в памяти в виде одного объекта QTableWidgetltem (элемент табличного виджета). Хранение данных в объектах типа «элемент» используется также виджетами QListWidget и QTreeWidget, которые работают с объектами QListWidgetItem и QTreeWidgetItem.

В Qt классы элементов могут использоваться вне таблиц как самостоятельные структуры данных. Например, QTableWidgetltem уже содержит некоторые атрибуты, в том числе строку, шрифт, цвет и пиктограмму, а также обратный указатель на QTableWidget. Такие элементы могут содержать также данные типа QVariant, включая зарегистрированные пользовательские типы, и, создавая подкласс такого элемента, можно обеспечить дополнительную функциональность.

Другие инструментальные средства предусматривают наличие в классах элементов указателя типа void для хранения пользовательских данных. В Qt используется более естественный подход с применением setData для типа QVariant, однако если требуется иметь указатель void, это можно сделать просто путем создания подкласса для класса элемента, который будет содержать переменную—указатель на член типа void.

Для данных, к которым предъявляются повышенные требования, например для больших наборов данных, для сложных элементов данных, для интеграции баз данных и для множественных представлений данных, Qt предоставляет набор классов «модель/представление», в которых данные отделены от их визуального представления. Эти классы рассматриваются в главе 10 .

01 Cell *Spreadsheet::cell(int row, int column) const

02 {

03 return static_cast<Cell *>(item(row, column));

04 }

Закрытая функция cell возвращает для заданной строки и столбца объект Cell. Она работает почти так же, как QTableWidget::item, но возвращает указатель на Cell, а не указатель на QTableWidgetltem.

01 QString Spreadsheet::text(int row, int column) const

02 {

03 Cell *c = cell(row, column);

04 if (с) {

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