Mark Summerfield (перевод Racheengel) |
Часто нам приходится отобразить пользователю форму, имеющую обязательные для заполнения поля. В данной статье представлен класс, который помогает работать с такими полями.
Если форма имеет обязательные поля, мы должны указать их, и активировать кнопку OK только в том случае, если все обязательные поля заполнены. Это можно сделать, используя класс MandatoryFieldGroup. Вот как его можно использовать в конструкторе диалога:
MoneyTransferDialog::MoneyTransferDialog(QWidget *parent) : QDialog(parent) { ... MandatoryFieldGroup *group = new MandatoryFieldGroup(this); group->add(toAccountComboBox); group->add(amountLineEdit); group->setOkButton(acceptButton); }
Как показано на скриншоте ниже, мы решили отмечать обязательные поля желтым фоном. (Для выпадающих списков, в некоторых стилях, желтый цвет появится только, если текст редактируем, либо список развернут.) Переключатели могут быть сделаны обязательными, если они принимают три состояния, и их начальное состояние - NoChange.
После того, как мы увидели использование, давайте посмотрим на определение:class MandatoryFieldGroup : public QObject { Q_OBJECT public: MandatoryFieldGroup(QObject *parent) : QObject(parent), okButton(0) {} void add(QWidget *widget); void remove(QWidget *widget); void setOkButton(QPushButton *button); private slots: void changed(); private: QValueList<QWidget *> widgets; QPushButton *okButton; };
Список widgets используется для хранения всех обязательных полей, а кнопка okButton - для связи с кнопкой диалога OK. Конструктор также требует инициализации okButton.
void MandatoryFieldGroup::add(QWidget *widget) { if (!widgets.contains(widget)) { if (widget->inherits("QCheckBox")) { connect(widget, SIGNAL(clicked()), this, SLOT(changed())); } else if (widget->inherits("QComboBox")) { connect(widget, SIGNAL(highlighted(int)), this, SLOT(changed())); } else if (widget->inherits("QLineEdit")) { connect(widget, SIGNAL(textChanged(const QString &)), this, SLOT(changed())); } else { qWarning("%s unhandled", widget->className()); return; } widget->setPaletteBackgroundColor(yellow); widgets.append(widget); changed(); } }
Если добавленный виджет еще не добавлен в группу обязательных полей, мы смотрим, от какого типа он порожден и соединяем наиболее подходящий его сигнал с нашим слотом changed(). Затем мы устанавливаем цвет фона, добавляем виджет в список обязательных полей, и вызываем слот changed() для обновления кнопки OK.
void MandatoryFieldGroup::setOkButton(QPushButton *button) { if (okButton && okButton != button) okButton->setEnabled(true); okButton = button; changed(); }
Если кнопка OK была изменена, мы активируем старую кнопку. Затем мы вызываем changed() для обновления ее состояния.
void MandatoryFieldGroup::changed() { if (!okButton) return; bool enable = true; QValueList<QWidget *>::const_iterator i; for (i = widgets.begin(); i != widgets.end(); ++i) { QWidget *widget = *i; if (widget->inherits("QCheckBox")) { if (((QCheckBox *)widget)->state() == QButton::NoChange) { enable = false; break; } } else if (widget->inherits("QComboBox")) { if (currentText().isEmpty()) { enable = false; break; } } else if (widget->inherits("QLineEdit")) { if (((QLineEdit *)widget)->text().isEmpty()) { enable = false; break; } } } okButton->setEnabled(enable); }
Если кнопка OK не была задана, мы не делаем ничего. Иначе, мы полагаем, что все обязательные поля имеют значения, и просматриваем их с целью проверки. Если какое-либо поле оказалось пустым (или неизменено, в случае переключателя), мы можем немедленно выйти из цикла, чтобы выключить кнопку OK. В конце мы соответственно включаем либо выключаем кнопку OK.
В некоторых ситуациях поле может перестать быть обязательным. Мы можем обеспечить это вызовом remove() (не приведено), при этом восстанавливается оригинальный цвет фона, виджет удаляется из списка обязательных полей, и вызывается changed() для обновления состояния кнопки OK.
Copyright © 2004 Trolltech | Trademarks |