La prochaine étape pour créer notre carnet d'adresses est d'ajouter un soupçon d'interactivité.
Nous allons fournir un bouton que l'utilisateur peut cliquer pour ajouter un nouveau contact. Une structure de données est aussi nécessaire afin de pouvoir stocker les contacts en mémoire.
Maintenant que nous avons mis en place les labels et les champs de saisie, nous ajoutons les boutons pour compléter le processus d'ajout d'un contact. Cela veut dire que notre fichier
addressbook.h
a maintenant trois objets
QPushButton
et trois slots publics correspondant.
public slots: void addContact(); void submitContact(); void cancel();
Un slot est une méthode qui répond à un signal. Nous allons voir ce concept en détail lorsque nous implémenterons la classe
AddressBook
. Pour une explication détaillée du concept de signal et slot, vous pouvez vous référer au document
信号和槽
.
Les trois objets
QPushButton
addButton
,
submitButton
et
cancelButton
sont maintenant inclus dans la déclaration des variables privées, avec
nameLine
et
addressText
du chapitre précédent.
private: QPushButton *addButton; QPushButton *submitButton; QPushButton *cancelButton; QLineEdit *nameLine; QTextEdit *addressText;
Nous avons besoin d'un conteneur pour stocker les contacts du carnet d'adresses, de façon à pouvoir les énumérer et les afficher. Un objet
QMap
,
contacts
, est utilisé pour ça, car il permet de stocker des paires clé-valeur: le nom du contact est la
clé
et l'adresse du contact est la
valeur
.
QMap<QString, QString> contacts;
QString oldName;
QString oldAddress;
};
Nous déclarons aussi deux objects
QString
privés:
oldName
et
oldAddress
. Ces objets sont nécessaires pour conserver le nom et l'adresse du dernier contact affiché avant que l'utilisateur ne clique sur le bouton "Add". Grâce à ces variables si l'utilisateur clique sur "Cancel", il est possible de revenir à l'affichage du dernier contact.
Dans le constructeur de
AddressBook
,
nameLine
et
addressText
sont mis en mode lecture seule, de façon à autoriser l'affichage mais pas la modification du contact courant.
...
nameLine->setReadOnly(true);
...
addressText->setReadOnly(true);
Ensuite, nous instancions les boutons
addButton
,
submitButton
, et
cancelButton
.
addButton = new QPushButton(tr("&Add"));
addButton->show();
submitButton = new QPushButton(tr("&Submit"));
submitButton->hide();
cancelButton = new QPushButton(tr("&Cancel"));
cancelButton->hide();
Le bouton
addButton
est affiché en invoquant la méthode
show()
, tandis que
submitButton
et
cancelButton
sont cachés en invoquant
hide()
. Ces deux boutons ne seront affichés que lorsque l'utilisateur cliquera sur "Add", et ceci est géré par la méthode
addContact()
décrite plus loin.
connect(addButton, SIGNAL(clicked()), this, SLOT(addContact()));
connect(submitButton, SIGNAL(clicked()), this, SLOT(submitContact()));
connect(cancelButton, SIGNAL(clicked()), this, SLOT(cancel()));
Nous connectons le signal clicked() de chaque bouton au slot qui gèrera l'action. L'image ci-dessous illustre ceci:
Ensuite, nous arrangeons proprement les boutons sur la droite du widget AddressBook, et nous utilisons un QVBoxLayout pour les aligner verticalement.
QVBoxLayout *buttonLayout1 = new QVBoxLayout;
buttonLayout1->addWidget(addButton, Qt::AlignTop);
buttonLayout1->addWidget(submitButton);
buttonLayout1->addWidget(cancelButton);
buttonLayout1->addStretch();
La methode addStretch() est utilisée pour assurer que les boutons ne sont pas répartis uniformément, mais regroupés dans la partie supperieure du widget. La figure ci-dessous montre la différence si addStretch() est utilisé ou pas.
Ensuite nous ajoutons
buttonLayout1
à
mainLayout
, en utilisant
addLayout()
. Ceci nous permet d'imbriquer les mises en page puisque
buttonLayout1
est maintenant un enfant de
mainLayout
.
QGridLayout *mainLayout = new QGridLayout;
mainLayout->addWidget(nameLabel, 0, 0);
mainLayout->addWidget(nameLine, 0, 1);
mainLayout->addWidget(addressLabel, 1, 0, Qt::AlignTop);
mainLayout->addWidget(addressText, 1, 1);
mainLayout->addLayout(buttonLayout1, 1, 2);
Les coordonnées du layout global ressemblent maintenant à ça:
Dans la méthode
addContact()
, nous stockons les détails du dernier contact affiché dans
oldName
et
oldAddress
. Ensuite, nous vidons ces champs de saisie et nous désactivons le mode lecture seule. Le focus est placé sur
nameLine
et on affiche
submitButton
et
cancelButton
.
void AddressBook::addContact() { oldName = nameLine->text(); oldAddress = addressText->toPlainText(); nameLine->clear(); addressText->clear(); nameLine->setReadOnly(false); nameLine->setFocus(Qt::OtherFocusReason); addressText->setReadOnly(false); addButton->setEnabled(false); submitButton->show(); cancelButton->show(); }
La méthode
submitContact()
peut être divisée en trois parties:
nameLine
et
addressText
et les stockons dans des objets
QString
. Nous les validons pour s'assurer que l'utilisateur n'a pas cliqué sur "Add" avec des champs de saisie vides; sinon un message est affiché avec
QMessageBox
pour rappeller à l'utilisateur que les deux champs doivent être complétés.
void AddressBook::submitContact() { QString 名称 = nameLine - > text(); QString address = addressText - > toPlainText(); if (name . isEmpty() | | address . isEmpty()) { QMessageBox :: information( this , tr( "Empty Field" ) , tr( "Please enter a name and address." )); return ; }
contacts
et nous affichons un
QMessageBox
pour informer l'utilisateur que le contact a été ajouté.
if (!contacts.contains(name)) {
contacts
.
insert(name
,
address);
QMessageBox
::
information(
this
,
tr(
"Add Successful"
)
,
tr(
"\"%1\" has been added to your address book."
)
.
arg(name));
}
else
{
QMessageBox
::
information(
this
,
tr(
"Add Unsuccessful"
)
,
tr(
"Sorry, \"%1\" is already in your address book."
)
.
arg(name));
return
;
}
Si le contact existe déjà, nous affichons un
QMessageBox
pour informer l'utilisateur du problème. Notre objet
contacts
est basé sur des paires clé-valeur formés par le nom et l'adresse, nous voulons nous assurer que la
clé
est unique.
if (contacts.isEmpty()) {
nameLine->clear();
addressText->clear();
}
nameLine->setReadOnly(true);
addressText->setReadOnly(true);
addButton->setEnabled(true);
submitButton->hide();
cancelButton->hide();
}
La capture d'écran ci-dessous montre l'affichage fournit par un objet QMessageBox , utilisé ici pour afficher un message d'information à l'utilisateur:
La méthode
cancel()
restaure les détails du dernier contact, active
addButton
, et cache
submitButton
et
cancelButton
.
void AddressBook::cancel() { nameLine->setText(oldName); nameLine->setReadOnly(true); addressText->setText(oldAddress); addressText->setReadOnly(true); addButton->setEnabled(true); submitButton->hide(); cancelButton->hide(); }
L'idée générale pour augmenter la flexibilité lors de l'ajout d'un contact est de donner la possiblité de cliquer sur "Add" ou "Cancel" à n'importe quel moment. L'organigramme ci-dessous reprend l'ensemble des interactions dévelopées jusqu'ici:
文件: