[Предыдущий: Адресная книга. Урок 2 - Добавление адресов] [Содержание] [Следующий: Урок 4]
Адресная книга. Урок 3 - Навигация по записям
Файлы:
Теперь приложение адресной книги наполовину готово. Нам нужно добавить несколько функций для навигации по контактам. Но сначала мы решим какого вида структуры данных мы будем использовать для хранения этих контактов.
В Уроке 2 мы использовали QMap с парами ключ-значение - имя контакта в качестве ключа и адрес контакта в качестве значения. Это хорошо подходит для нашего случая. Однако для того, чтобы передвигаться по записям и отображать каждую из них необходимо небольшое улучшение.
Мы улучшим QMap сделав его копией структуры данных, аналогичной циклически связанному (circularly-linked) списку, где все элементы соединены между собой, включая первый и последние элементы. Рисунок ниже иллюстрирует эту структуру данных.
Определение класса AddressBook
Для того, чтобы добавить функции навигации в приложение адресной книги нам нужно добавить к нашему классу AddressBook ещё два слота: next() и previous(). Добавляем их в наш файл addressbook.h:
void next();
void previous();
Нам также нужны ещё два объекта QPushButton, поэтому мы объявляем nextButton и previousButton как закрытые переменные:
QPushButton *nextButton;
QPushButton *previousButton;
Реализация класса AddressBook
В конструкторе класса AddressBook в файле addressbook.cpp мы создаем объекты nextButton и previousButton и по умолчанию отключаем их. Сделано это потому, что навигация разрешена только тогда, когда в адресной книге имеется более одного контакта.
nextButton = new QPushButton(tr("&Next"));
nextButton->setEnabled(false);
previousButton = new QPushButton(tr("&Previous"));
previousButton->setEnabled(false);
Затем мы соединяем эти кнопки с соответствующими им слотами:
connect(nextButton, SIGNAL(clicked()), this, SLOT(next()));
connect(previousButton, SIGNAL(clicked()), this, SLOT(previous()));
Рисунок ниже - ожидаемый графический пользовательский интерфейс. Заметим, что он вплотную приблизился к окончательному результату.
Мы следуем базовым соглашениям для функций next() и previous(), размещая nextButton справа, а previousButton - слева. Для того, чтобы добиться этой наглядной компоновки, мы используем QHBoxLayout чтобы разместить виджеты в ряд:
QHBoxLayout *buttonLayout2 = new QHBoxLayout;
buttonLayout2->addWidget(previousButton);
buttonLayout2->addWidget(nextButton);
Объект класса QHBoxLayout - buttonLayout2 - затем добавляется в mainLayout.
mainLayout->addLayout(buttonLayout2, 3, 1);
Рисунок ниже показывает координаты виджетов в mainLayout.
Внутри нашей функции addContact() мы отключаем эти кнопки, чтобы не искушать пользователя навигацией во время добавления контакта.
nextButton->setEnabled(false);
previousButton->setEnabled(false);
Также в нашей функции submitContact() мы разблокируем навигационные кнопки, nextButton и previousButton, в зависимости от размера contacts. Как рассматривалось выше, навигация включена только тогда, когда в адресной книге имеется более одного контакта. Следующие строки кода демонстрируют как это сделать:
int number = contacts.size();
nextButton->setEnabled(number > 1);
previousButton->setEnabled(number > 1);
Мы включили эти строки в функцию cancel().
Вспомните, что мы намеревались эмулировать циклически связанный список с помощью объекта класса QMap - contacts. Таким образом, в функции next() мы применяем итератор для contacts, а затем:
- Если итератор находится не в конце contacts, мы увеличиваем его на единицу.
- Если итератор находится в конце contacts, мы передвигаем его в начало contacts. Это создает иллюзию того, что наш QMap работает как циклически связанный список.
void AddressBook::next()
{
QString name = nameLine->text();
QMap<QString, QString>::iterator i = contacts.find(name);
if (i != contacts.end())
i++;
if (i == contacts.end())
i = contacts.begin();
nameLine->setText(i.key());
addressText->setText(i.value());
}
Поскольку мы выполняем итерацию на корректный объект в списке contacts, то мы отображаем его содержимое в nameLine и addressText.
Подобным же образом для функции previous() мы получаем итератор для contacts и далее:
- Если итератор находится в конце contacts, мы очищаем экран и возвращаемся.
- Если итератор находится в начале contacts, мы перемещаем его в конец.
- Затем мы уменьшаем итератор на единицу.
void AddressBook::previous()
{
QString name = nameLine->text();
QMap<QString, QString>::iterator i = contacts.find(name);
if (i == contacts.end()){
nameLine->clear();
addressText->clear();
return;
}
if (i == contacts.begin())
i = contacts.end();
i--;
nameLine->setText(i.key());
addressText->setText(i.value());
}
Вновь мы отображаем содержимое текущего объекта в contacts.
[Предыдущий: Адресная книга. Урок 2 - Добавление адресов] [Содержание] [Следующий: Урок 4]
Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies) |
Торговые марки |
Qt 4.5.3 |
|